Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
包含混合类型值的Scala映射_Scala - Fatal编程技术网

包含混合类型值的Scala映射

包含混合类型值的Scala映射,scala,Scala,我有一个返回的函数(groovy代码) 在scala中,我在上面更改为scala映射,但随后我被迫将其声明为 Map[String, Any] 但这样做的缺点是,如果我访问一个密钥,例如 地图(“文字”) 我必须加上样板 map2("words").asInstanceOf[String] scala中有没有更好的方法不需要我添加instanceof?为了避免强制转换并从静态键入中获益,您可以返回元组(String,Int,Int): 或者对结果使用case类: case class MyR

我有一个返回的函数(groovy代码)

在scala中,我在上面更改为scala映射,但随后我被迫将其声明为

Map[String, Any]
但这样做的缺点是,如果我访问一个密钥,例如 地图(“文字”) 我必须加上样板

map2("words").asInstanceOf[String]

scala中有没有更好的方法不需要我添加instanceof?

为了避免强制转换并从静态键入中获益,您可以返回元组
(String,Int,Int)

或者对结果使用case类:

case class MyResult(line: String, row: Int, col: Int)

def getResult = MyResult("one two", 23, 45)

val res = getResult
res.line // the line

// alternatively use the extractor provided by the case class
val MyResult(line, row, _) = getResult // col is discarded
line // the line
row  // the row

我更喜欢case类,因为字段是命名的,它实际上只多了一行。

编辑:我知道您得到的映射是原样的,需要一种更干净的接口。当然,如果适用的话,案例类方法要优于我下面提出的方法


如果键始终映射到相同的值类型,则可以执行以下操作:

class TypedKey[T] {
  def name = {
    // assumes you declare only `object` instances
    val simpleName = getClass.getSimpleName
    val moduleName = if (simpleName.endsWith("$")) simpleName.substring(0, simpleName.size - 1) else simpleName
    val lastDollar = moduleName.lastIndexOf('$')
    if (lastDollar == -1) moduleName else moduleName.substring(lastDollar + 1)
  }
}

object RubyKeys {
  object words extends TypedKey[String]
  object row extends TypedKey[Int]
  object col extends TypedKey[Int]
}

class MapWrapper(val underlying: Map[String, Any]) {
  def apply[T](key: TypedKey[T]) = underlying(key.name).asInstanceOf[T]
}

def main(args: Array[String]) {

  val map = Map("words" -> "one two", "row" -> 23, "col" -> 45)
  val wrapper = new MapWrapper(map)

  import RubyKeys._

  val w = wrapper(words) // String
  val r = wrapper(row)   // Int
  val c = wrapper(col)   // Int
  println(w, r, c)
}

在您的示例中,只有两种可能的值类型将允许将
类型与子类型
Left
Right
一起使用:

val m = Map("words" -> Left("one two"), "rows"-> Right(23), "cols"-> Right(45))

如果您从地图中获取一个值,您可以检查您拥有的内容,例如使用模式匹配或使用
isLeft
isRight
,并相应地“展开”

在这里,案例类是您的朋友。如果映射的键是case类,则可以强制客户端代码正确处理类型(并强制它正确处理所有类型)

S:\>scala
欢迎使用Scala版本2.9.0.final(Java热点(TM)64位服务器虚拟机,Java 1.6.025)。
键入要计算的表达式。
键入:有关详细信息的帮助。
scala>密封抽象类东西;
定义类事物
scala>case类烤面包机(slices:Int)扩展了东西;
限定等级烤面包机
scala>case类Bucket(内容:String)扩展了东西;
定义类存储桶
scala>val things=Map(“烤面包店”->烤面包机(2),“巴克”->桶(“东西”);
things:scala.collection.immutable.Map[java.lang.String,可以用Thing序列化的产品]=Map(toasty->Toaster(2),buck->Bucket(stu
(ff))
scala>for(x println(k+“”+s)
案例(k,Bucket(c))=>println(k+“”+c)
}
烤面包2
雄鹿的东西
这里的关键是match语句正在分解各种大小写,并为您提供正确类型的变量以匹配其中的字段。通过声明抽象类为密封类,您可以让编译器知道它拥有所有可用的子类。有了这些信息,它可以告诉您何时缺少大小写,它还可以做进一步的优化

class TypedKey[T] {
  def name = {
    // assumes you declare only `object` instances
    val simpleName = getClass.getSimpleName
    val moduleName = if (simpleName.endsWith("$")) simpleName.substring(0, simpleName.size - 1) else simpleName
    val lastDollar = moduleName.lastIndexOf('$')
    if (lastDollar == -1) moduleName else moduleName.substring(lastDollar + 1)
  }
}

object RubyKeys {
  object words extends TypedKey[String]
  object row extends TypedKey[Int]
  object col extends TypedKey[Int]
}

class MapWrapper(val underlying: Map[String, Any]) {
  def apply[T](key: TypedKey[T]) = underlying(key.name).asInstanceOf[T]
}

def main(args: Array[String]) {

  val map = Map("words" -> "one two", "row" -> 23, "col" -> 45)
  val wrapper = new MapWrapper(map)

  import RubyKeys._

  val w = wrapper(words) // String
  val r = wrapper(row)   // Int
  val c = wrapper(col)   // Int
  println(w, r, c)
}
val m = Map("words" -> Left("one two"), "rows"-> Right(23), "cols"-> Right(45))
        S:\>scala
    Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_25).
    Type in expressions to have them evaluated.
    Type :help for more information.

    scala> sealed abstract class Thing;
    defined class Thing

    scala> case class Toaster(slices: Int) extends Thing;
    defined class Toaster

    scala> case class Bucket(contents: String) extends Thing;
    defined class Bucket

    scala> val things = Map("toasty" -> Toaster(2), "buck" -> Bucket("stuff"));
things: scala.collection.immutable.Map[java.lang.String,Product with Serializable with Thing] = Map(toasty -> Toaster(2), buck -> Bucket(stu
ff))

scala> for (x <- things) x match {
     case (k,Toaster(s)) => println(k + " " + s)
     case (k,Bucket(c)) => println(k + " " + c)
     }
toasty 2
buck stuff