techkuz
techkuz

Reputation: 3956

andThen with square brackets and underscore in Scala function

I have two functions

val mul3 = 3*(_: Double)
val pow2 = (x: Double) => x*x

What I don't understand how it works at all is this:

println((pow2.andThen[Double] _ )(mul3)(5))

1) I thought andThen operates with results of the function to the left, but here it is [Double] _ - what is this? (I was expecting something like pow2 andThen mul3)
2) Why is mul3 passed to pow2 if pow2 expects Double? (mul3(pow2) gives an error)
3) What is being passed to pow2? Is it mul3 or 15?
4) What does . mean?

scala fiddle

Upvotes: 1

Views: 299

Answers (1)

Lets go step by step.

val mul3 = 3*(_: Double)

Is a Function from a Double to another Double. Thus, is type is Function1[Double, Double].
The same applies to:

val pow2 = (x: Double) => x*x

Now, remember that in Scala, everything is an object. And that there are not operators, only methods. So:

pow2.andThen[Double]

Is calling the andThen on method on the Function1 class.
As you can see on the scaldoc, that method receives another function. Also, it is parametric in the return type of the second function, which determines the return type of the composed function that is returned.
So the [Double] part is just specifying that type.

pow2.andThen[Double] _

Is using the underscore syntax to create another function.
The above line is equivalent to:

f => pow2.andThen[Double](f)

So, it is creating a function that takes another function as input, and returns another function. The resulting function will call pow2 first and then call the function passed as the argument.
Thus, it is of type Function1[Function1[Double, Double], Function[Double, Double]].

Then

(pow2.andThen[Double] _ )(mul3)

Is passing mul3 as the argument of that function, returning a final function (Function1[Double, Doule]) that calls pow2 first and pass the result to mul3.

Finally

(pow2.andThen[Double] _ )(mul3)(5)

Is calling the resulting function with 5 as is input.
After substitution, the code is equivalent to:

x => mul3(pow2(x))
x => 3 * (x * x)
5 => 3 * (x * x)
3 * (5 * 5)
75.0

Side note, IMHO, that code is very cryptic and far for what I would call idiomatic in Scala.

Upvotes: 1

Related Questions