加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Martin Odersky的ScalaDay 2011的例子:获得地图?

发布时间:2020-12-16 09:43:08 所属栏目:安全 来源:网络整理
导读:我正在通过 Odersky’s ScalaDays 2011 keynote talk工作,当我到达这条特定的行(分配charCode)时,他构建了一个非常少的代码行的电话号码同义词生成器: val mnem: Map[Char,String] = // phone digits to mnemonic chars (e.g. '2' - "ABC")val charCode:
我正在通过 Odersky’s ScalaDays 2011 keynote talk工作,当我到达这条特定的行(分配charCode)时,他构建了一个非常少的代码行的电话号码同义词生成器:

val mnem: Map[Char,String] = // phone digits to mnemonic chars (e.g. '2' -> "ABC")
val charCode: Map[Char,Char] = for ((digit,str) <- mnem; letter <- str)
    yield (letter -> digit)   // gives ('A','2'),('B','2') etc

为什么类型为Map的charCode?

当我在其他例子中产生元组时,我只是获得一系列元组,而不是地图。例如:

scala> for (i <- 1 to 3) yield (i -> (i+1))
res16: scala.collection.immutable.IndexedSeq[(Int,Int)] = Vector((1,2),(2,3),(3,4))

人们可以很容易地将它转换成具有toMap()的地图,就像…

scala> (for (i <- 1 to 3) yield (i -> (i+1))).toMap
res17: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2,2 -> 3,3 -> 4)

…但不知何故,Odersky的例子避免了这一点。

什么Scala魔法,如果有的话,我俯瞰这里?

附录1:隐式转换?我想添加一些关于Oxbow Lake的评论的细节(注意:我的评论可能会部分错误,略有误解,也许是他所得到的)。

我怀疑由于需要地图而发生某种隐式转换。所以我在翻译中尝试过Odersky的迭代器,没有提示它应该产生什么:

scala> val mnem = Map('2' -> "ABC",'3' -> "DEF",'4' -> "GHI") // leaving as a map,still
scala> for ((digit,str) <- mnem; letter <- str) yield (letter,digit)
res18: scala.collection.immutable.Map[Char,Char] = Map(E -> 3,F -> 3,A -> 2,I -> 4,G -> 4,B -> 2,C -> 2,H -> 4,D -> 3)

(请注意,我在这里离开mnem作为地图。)

同样,告诉编译器我想要一个地图没有改变我自己的结果:

scala> val x: Map[Int,Int] = for (i <- 1 to 3) yield (i -> (i+1))
<console>:7: error: type mismatch;
 found   : scala.collection.immutable.IndexedSeq[(Int,Int)]
 required: Map[Int,Int]
       val x: Map[Int,Int] = for (i <- 1 to 3) yield (i -> (i+1))

另一方面,遵循东方的提示(这似乎也是OL所说的),以下(dorky)修改确实产生了一个地图:

scala> for ((i,j) <- Map(1 -> 2,2 -> 2)) yield (i -> (i+1))
res20: scala.collection.immutable.Map[Int,2 -> 3)

所以如果迭代的值来自地图,那么地图是不是会产生的?

我希望通过以下方式来理解答案:(a)将“for”循环转换为其长时间的等价物(一个调用/调用映射)和(b)了解什么意义被神奇地引用。

附录2:统一返回类型:(huynhjl :)那似乎是这样。我的第一个例子转换为

(1 to 3).map(i => (i,i+1)) // IndexedSeq[(Int,Int)]

而第二个变成类似于这样的东西:

Map(1 -> 2,2 -> 2).map(i => (i._1,i._1+1)) // Map[Int,Int]

那么“Map.map”的类型就是

def map [B,That] (f: ((A,B)) ? B)(implicit bf: CanBuildFrom[Map[A,B],B,That]): That

啊,琐事;-)

附录3:好的,那太简单了吧。 Miles Sabin提供了一个更正确的desugaring,在下面。更微不足道;-)

解决方法

了解你为什么得到一个地图回来比较容易理解,

val charCode: Map[Char,str) <- mnem; letter <- str)
  yield (letter -> digit)

相当于,

val charCode = mnem.flatMap {
  case (digit,str) => str.map { letter => (letter -> digit) }
}

因此,这里为charCode推断的类型将是应用于Map的flatMap的结果类型。 flatMap的签名相当复杂,

def flatMap [B,That]
  (f: ((A,B)) => GenTraversableOnce[B])
  (implicit bf: CanBuildFrom[Map[A,That]): That

因为它提供了Scala编译器需要计算适当结果类型的基础架构,因为Map的类型和函数的类型(Flat)Map’跨越它。

如其他地方所述,集合框架的设计方式使得集装箱将(平面)映射到尽可能相同形状的容器。在这种情况下,我们映射Map [Char,String],因此它的元素相当于对(Char,String)。我们映射的函数是生成对(Char,Char),它们连接可以给我们一个Map [Char,Char]。

我们可以通过查找相应的CanBuildFrom实例来验证编译器是否也相信这一点,

scala> import scala.collection.generic.CanBuildFrom
import scala.collection.generic.CanBuildFrom

scala> implicitly[CanBuildFrom[Map[Char,String],(Char,Char),Map[Char,Char]]]
res0: scala.collection.generic.CanBuildFrom[Map[Char,Char]] = scala.collection.generic.GenMapFactory$MapCanBuildFrom@1d7bd99

请注意,CanBuildFrom的最后一个参数是Map [Char,Char]。这将在flatMap的签名中修复“That”类型的参数,这给了我们这个flatMap的结果类型,因此推断出charCode的类型。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读