Help understanding a function parameter and f(next)


#1

I am going through the Scala tutorial here:
http://docs.scala-lang.org/tutorials/tour/mixin-class-composition.html.html

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.

Thanks for helping me understanding this.


#2

Here, f is not applied to the method next, but only the return value of
next.


#3

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

#4

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.

Is my understanding correct so far?


#5

That makes sense. It the value of the expression represented by next that f is being applied to. Thank you.


#6

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.


#7

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


#8

Okay, I am a little confused about this:
f: T => Unit

How do we interpret this exactly?
To my mind it is: Pass in a function that is represented by a "type variable: parameter and retun Unit?

Is that how it is or am I missing something?


#9

here’s a pull request that adds the parens to next in the tutorial: https://github.com/scala/scala.github.com/pull/837


#10

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.


#11

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.

#12

Thank you for your reply. Appreciate it.


#13

Thank you for your reply.