I've been told that Scala provides capability to model UNTIL, REPEAT
control flow.
While studying the capability, I've found the code:
// 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)
Why is the new
keyword in REPEAT
function needed?
new { def ...}
construct creates a new anonymous object with structural type AnyRef{def ...}
:
scala> val aa = new { def kk = "bb" }
aa: AnyRef{def kk: String}
Your UNTIL
method is accessible because of feature called "reflective access of structural type member", and you should also have an import scala.language.reflectiveCalls
, at least in Scala 2.11.2 as a result of 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
Note, that it's a little bit slower than defining class Repeatable {def UNTIL = ...}
, because (for JVM) your REPEAT
function just returns Object
(AnyRef) and there is no type to cast from it, so Scala invokes UNTIL
using reflection. It also didn't introduce some synthetic class because structural type can match any existing class (any other class with appropriate UNTIL
method).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With