有人告诉我Scala提供了对UNTIL, REPEAT控制流进行建模的功能。

在研究功能时,我发现了以下代码:

// ref: https://gist.github.com/metasim/7503601
def REPEAT(body: => Unit) = new {
  def UNTIL(condition: => Boolean): Unit = {
    body
    if (condition) ()
    else UNTIL(condition)
  }
}

// test code
REPEAT {
  x = x + 1
} UNTIL (x > 3)

为什么需要new函数中的REPEAT关键字?

最佳答案

new { def ...}构造使用structural type AnyRef{def ...}创建一个新的匿名对象:

scala> val aa = new { def kk = "bb" }
aa: AnyRef{def kk: String}

由于称为“结构类型成员的反射访问”的功能,可以访问UNTIL方法,并且由于SIP 18: Modularizing Language Features,至少在Scala 2.11.2中,还应该具有import scala.language.reflectiveCalls:
scala> aa.kk
<console>:9: warning: reflective access of structural type member method kk should be enabled
by making the implicit value scala.language.reflectiveCalls visible.
This can be achieved by adding the import clause 'import scala.language.reflectiveCalls'
or by setting the compiler option -language:reflectiveCalls.
See the Scala docs for value scala.language.reflectiveCalls for a discussion
why the feature should be explicitly enabled.
              aa.kk
                 ^
res0: String = bb

注意,这比定义class Repeatable {def UNTIL = ...}慢一点,因为(对于JVM)您的REPEAT函数仅返回Object(AnyRef),并且没有类型可转换,因此Scala使用反射调用UNTIL。它还没有引入任何综合类,因为结构类型可以匹配任何现有类(任何其他具有适当UNTIL方法的类)。

10-06 01:00