为什么模拟UNTIL / REPEAT的代码需要新的关键字?

时间:2014-12-21 07:09:23

标签: scala

我被告知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关键字?

1 个答案:

答案 0 :(得分:3)

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

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

您的UNTIL方法是可访问的,因为称为"结构类型成员"的反射访问,您还应该有import scala.language.reflectiveCalls,至少在Scala 2.11.2中SIP 18: Modularizing Language Features的结果:

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方法)。