Right now, I am at the Class Composition With Mixins chapter.
What I do not understand is the parameter for the foreach method:
abstract class AbsIterator {
type T
def hasNext: Boolean
def next: T
}
trait RichIterator extends AbsIterator {
def foreach(f: T => Unit): Unit = while (hasNext) f(next)
}
I think this is an example of a higher-order function where a function is passed into another function (even a method perhaps?) as an argument
I have also gone through James Ward’s Tutorial to understand the concept of passing a function as an argument into a method.
But I am stumped by this: f(next)
What is going on here that I am missing?
I understand that ‘f’ is a function type that represents a function that takes in a type T and returns Unit. After that, what is f(next). It looks like a function call to me, but it is taking in a method ‘next’?
I am not sure how to interpret this.
It might help you if next were defined as def next():T and then the call to f looks like f(next()). Scala doesn’t require parentheses on function/method invocation when there are no arguments, but I would argue that next should have one here. The general style guideline is that methods/functions with side effects should have the parentheses. the next method has the side effect of advancing the iterator.
So back to your question, this is calling next to get the next value, and then passing the result of that call into the function f that was supplied by the outside caller. We could expand the code out even more. See if you like this better.
abstract class AbsIterator {
type T
def hasNext: Boolean
def next(): T
}
trait RichIterator extends AbsIterator {
def foreach(f: T => Unit): Unit = {
while (hasNext) {
val n = next()
f(n)
}
}
}
This is so much clearer. I was not aware of the fact that methods/functions with side effects should have the parentheses, until you just mentioned it.
The newly rewritten method foreach is so much clearer. It nicely adds to Curoli’s answer that f is not applied to next. Rather it is the value returned by next, since everything in Scala is an expression.
I think that you have it. You were very close initially. Note that other than putting the parentheses on next, the original version is probably in the style that most people would would use for Scala. My longer version is more verbose, and only adds readability to those who are new to the language.
I agree. The readability matters. The verbose version is great for me. That way, I can start connecting the verbose version to its “original short or sugar” version. Eventually I could get close to the original version…
Thanks for your time
Here, f is a function which takes a single parameter of type T and
returns Unit. Unit is a type with a single value that means here
(roughly) “doesn’t return anything”. (This is vaguely similar to 'void’
in Java or C, but don’t go too far with that comparison.) Unit is used
in places where you want to indicate that a function or method only has
side effects, and doesn’t return anything.
Others have already answered fully, but let me quickly add my heuristic for understanding Scala syntax. When you see f(next), you have to go back and look at the declarations of each symbol:
f: T => Unit: function that takes an argument of type T and returns (): Unit
def next: T: method that returns a value of type T. The important part is that anything declared as a method, i.e. with a def, will trigger a method call whenever it appears in the code. Scala allows methods without parameters, so even just next will trigger a method call and return a value of type T.