Scala“ < - ”用于理解
-
04-10-2019 - |
题
我发现Scala总是对任何事物都有“自然的解释”。总是像“哦”,但这只是一个函数,与此对象和该参数有关”。从某种意义上说,从其他语言中知道的那样,没有什么真正是编译器魔术。
我的问题是 <- 按照以下代码中使用的运算符:
for(i <- 0 to 10) println(i)
在此示例中,我可以看到它被改写为类似的东西:
0.to(10).foreach((i:Int)=>println(i))
但这不能解释如何 一世 进入foreach函数内部的匿名函数。在你写的时候 一世 它不是一个对象,也不是声明的变量。那么,这是什么,如何将其转移到Foreach的内部?
我的猜测是我终于发现了实际上的东西 编译器魔术
谢谢你的时间。
澄清, 我的问题是:< - 运算符在代码的第一行中如何工作,因为我不是一个可以称为函数的对象。
解决方案
<-
是语言定义的关键字符号, =>
但与众不同 ->
(这是一个定义的符号)。因为它是基本的Scala语法的一部分,因此可以用于创建绑定(对于 i
在您的示例中)这是用户定义的构造无法完成的。
其他提示
为了增强戴夫的回答,这是Scala语言规范中“理解”的翻译模式:
理解
for (enums) yield e
评估表达e
对于由枚举者产生的每个绑定。枚举序列始终以生成器开头。随后可以是进一步的发电机,价值定义或警卫。发电机
p <- e
从表达产生结合物e
以某种方式与模式匹配p
. 。值定义val p = e
绑定值名称p
(或模式中的几个名称p
)为了评估表达式e
. 。警卫if e
包含限制列出结合的布尔表达。发电机和警卫的确切含义是通过转换为四种方法的调用来定义的:
map
,filter
,flatMap
, , 和foreach
. 。这些方法可以以不同的方式用于不同的载体类型。翻译方案如下。第一步,每个发电机
p <- e
, ,其中p不可辩驳的(第8.1节)e
被取代p <- e.filter { case p => true; case _ => false }
然后,重复应用以下规则,直到消除所有理解为止。
一个理解
for (p <- e) yield e0
被翻译成e.map { case p => e0 }
.一个理解
for (p <- e) e0
被翻译成e.foreach { case p => e0 }
.一个理解
for (p <- e; p0 <- e0 . . .) yield e00
, , 在哪里 。 。 。是(可能是空的)发电机或警卫序列,被翻译成:e.flatMap { case p => for (p0 <- e0 . . .) yield e00 }
.一个理解
for (p <- e; p0 <- e0 . . .) e00
在哪里 。 。 。是(可能是空的)发电机或警卫序列,被翻译成:e.foreach { case p => for (p0 <- e0 . . .) e00 }
.发电机
p <- e
其次是警卫if g
被翻译成一个发电机:
p <- e.filter((x1, . . . , xn) => g )
在哪里x1
, . . . ,xn
是自由变量p
.发电机
p <- e
其次是价值定义val p0 = e0
被翻译成以下一个值的发电机,其中x
和x0
是新名称:val (p, p0) <- for(x@p <- e) yield { val x0@p0 = e0; (x, x0) }
在这种情况下,这确实是编译器的魔术。翻译从易常/地图/地图/flatmap形式的翻译是一种特殊的脱计划,就像对更新的特殊形式的转换和应用方法一样。