有人告诉我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
方法的类)。