Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I have an answer to your question but first...</p> <p>This is the most minimal recursive implementation of <code>max</code> I've ever been able to think up:</p> <pre><code>def max(xs: List[Int]): Option[Int] = xs match { case Nil =&gt; None case List(x: Int) =&gt; Some(x) case x :: y :: rest =&gt; max( (if (x &gt; y) x else y) :: rest ) } </code></pre> <p>(OK, my original version was ever so slightly more minimal but I wrote that in Scheme which doesn't have Option or type safety etc.) It doesn't need an accumulator or a local helper function because it compares the first two items on the list and discards the smaller, a process which - performed recursively - inevitably leaves you with a list of just one element which must be bigger than all the rest.</p> <p>OK, why your original solution doesn't work... It's quite simple: you do nothing with the return value from the recursive call to <code>max</code>. <em>All</em> you had to do was change the line</p> <pre><code>max(remaining) </code></pre> <p>to</p> <pre><code>largest = max(remaining) </code></pre> <p>and your function would work. It wouldn't be the prettiest solution, but it would work. As it is, your code looks as if it assumes that changing the value of <code>largest</code> inside the recursive call will change it in the outside context from which it was called. But each new call to <code>max</code> creates a completely new version of <code>largest</code> which only exists inside that new iteration of the function. Your code then throws away the return value from <code>max(remaining)</code> and returns the original value of <code>largest</code>, which hasn't changed.</p> <p>Another way to solve this would have been to use a local (inner) function <em>after</em> declaring <code>var largest</code>. That would have looked like this:</p> <pre><code>def max(xs: List[Int]): Int = { var largest = xs.head def loop(ys: List[Int]) { if (!ys.isEmpty) { var next = ys.head largest = if (largest &gt; next) largest else next loop(ys.tail) } } loop(xs.tail) return largest } </code></pre> <p>Generally, though, it is better to have recursive functions be entirely self-contained (that is, not to look at or change external variables but only at their input) and to return a meaningful value.</p> <p>When writing a recursive solution of this kind, it often helps to think in reverse. Think first about what things are going to look like when you get to the end of the list. What is the exit condition? What will things look like and where will I find the value to return? </p> <p>If you do this, then the <code>case</code> which you use to exit the recursive function (by returning a simple value rather than making another recursive call) is usually very simple. The other <code>case</code> matches just need to deal with a) invalid input and b) what to do if you are not yet at the end. a) is usually simple and b) can usually be broken down into just a few different situations, each with a simple thing to do before making another recursive call.</p> <p>If you look at my solution, you'll see that the first <code>case</code> deals with invalid input, the second is my exit condition and the third is "what to do if we're not at the end".</p> <p>In many other recursive solutions, <code>Nil</code> is the natural end of the recursion.</p> <p>This is the point at which I (as always) recommend reading <a href="http://www.ccs.neu.edu/home/matthias/BTLS/" rel="nofollow">The Little Schemer</a>. It teaches you recursion (and basic Scheme) at the same time (both of which are very good things to learn).</p> <p>It has been pointed out that Scala has some powerful functions which can help you avoid recursion (or hide the messy details of it), but to use them well you really do need to understand how recursion works.</p>
    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.
 

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