Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This answer is a synthesis of the partial answers provided by both 0__ and Nicolas Rinaudo. </p> <p><strong>Summary:</strong></p> <p>There are many convenient (but also highly intertwined) assumptions being made by the Scala compiler.</p> <ol> <li>Scala treats <code>extends (A =&gt; B)</code> as synonymous with <code>extends Function1[A, B]</code> (<a href="http://www.scala-lang.org/api/current/index.html#scala.Function1" rel="nofollow">ScalaDoc for Function1[+T1, -R]</a>)</li> <li>A concrete implementation of Function1's inherited abstract method <code>apply(x: A): B</code> must be provided; <code>def apply(x: A): B = cache.getOrElseUpdate(x, f(x))</code></li> <li>Scala assumes an implied <code>match</code> for the code block starting with <code>= Memo {</code></li> <li>Scala passes the content between <code>{}</code> started in item 3 as a parameter to the Memo case class constructor</li> <li>Scala assumes an implied type between <code>{}</code> started in item 3 as <code>PartialFunction[Int, BigInt]</code> and the compiler uses the "match" code block as the override for the PartialFunction method's <code>apply()</code> and then provides an additional override for the PartialFunction's method <code>isDefinedAt()</code>. </li> </ol> <p><strong>Details:</strong></p> <p>The first code block defining the case class Memo can be written more verbosely as such: </p> <pre><code>case class Memo[A,B](f: A =&gt; B) extends Function1[A, B] { //replaced (A =&gt; B) with what it's translated to mean by the Scala compiler private val cache = mutable.Map.empty[A, B] def apply(x: A): B = cache.getOrElseUpdate(x, f(x)) //concrete implementation of unimplemented method defined in parent class, Function1 } </code></pre> <p>The second code block defining the val fibanocci can be written more verbosely as such:</p> <pre><code>lazy val fibonacci: Memo[Int, BigInt] = { Memo.apply( new PartialFunction[Int, BigInt] { override def apply(x: Int): BigInt = { x match { case 0 =&gt; 0 case 1 =&gt; 1 case n =&gt; fibonacci(n-1) + fibonacci(n-2) } } override def isDefinedAt(x: Int): Boolean = true } ) } </code></pre> <p>Had to add <code>lazy</code> to the second code block's val in order to deal with a self-referential problem in the line <code>case n =&gt; fibonacci(n-1) + fibonacci(n-2)</code>.</p> <p>And finally, an example usage of fibonacci is:</p> <pre><code>val x:BigInt = fibonacci(20) //returns 6765 (almost instantly) </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload