我发现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 被翻译成以下一个值的发电机,其中 xx0 是新名称:

    val (p, p0) <- 
      for(x@p <- e) yield { val x0@p0 = e0; (x, x0) }
    

在这种情况下,这确实是编译器的魔术。翻译从易常/地图/地图/flatmap形式的翻译是一种特殊的脱计划,就像对更新的特殊形式的转换和应用方法一样。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top