Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the code to model UNTIL/REPEAT require new keyword?

Tags:

scala

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?

like image 536
1ambda Avatar asked Oct 19 '22 20:10

1ambda


1 Answers

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).

like image 82
dk14 Avatar answered Oct 22 '22 23:10

dk14