Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <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>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COI believe your `2.` is not needed (nor really correct), since `override` is an annotation that you add to help the compiler but is never required nor present in the compiler's output. Your `3.` is slightly wrong: there is no implied match - `a match {...` just means that the partial function is called with argument `a`, and in our case, it's passed as a parameter, not called. `4.` is a simplification: the partial function is passed to the `apply` method of the companion object, which *then* passes it to the constructor. You're 100% correct about the `lazy`, apologies for the oversight.
      singulars
    2. CO@NicolasRinaudo My purpose is to show all the assumptions being made by being over-verbose; i.e. use as few of the compiler simplifications as possible. Hence, my using "override" in item 2. BTW, I think "override" is only _optional_ when the override is to an abstract method. It is required when overriding a non-abstract method, right?
      singulars
    3. CO@NicolasRinaudo Per item 3, again I am attempting to show assumption leaps being made by the compiler simplifications. So, I am intentionally being Java level verbose with types. So, given what I have read numerous places, the PartialFunction being produced is from the compiler converting the match (i.e. the block of case statements) into a PartialFunction. Are you saying this is not what is happening?
      singulars
 

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