raulk
raulk

Reputation: 2859

Scala function composition: brackets and types

(1) Having defined two functions in the Scala REPL:

scala> def f(s: String) = "f(" + s + ")"
f: (s: String)String

scala> def g(s: String) = "g(" + s + ")"
g: (s: String)String

(2) Composing them without brackets works as expected:

scala> f _ compose g _
res18: String => String = <function1>

(3) Composing them with brackets doesn't:

scala> f(_).compose(g(_))
<console>:14: error: missing parameter type for expanded function ((x$1) => f(x$1).compose(((x$2) => g(x$2))))
       f(_).compose(g(_))
         ^
<console>:14: error: missing parameter type for expanded function ((x$2) => g(x$2))
       f(_).compose(g(_))
                      ^
<console>:14: error: type mismatch;
 found   : String
 required: Int
       f(_).compose(g(_))
                     ^

Question 1: Can somebody explain why?

Question 2: Why the type mismatch? Why is Scala expecting an Int at all?

(4) Surrounding f(_) with brackets seems to help a little bit, by making the first two errors go away:

scala> (f(_)).compose(g(_))
<console>:14: error: missing parameter type for expanded function ((x$2) => g(x$2))
       (f(_)).compose(g(_))
                    ^

Question 3: Why do these brackets help?

Question 4: Why does Scala need the parameter types, even though they are clearly defined in f and g respectively?

(5) Finally, adding the parameter type makes it work:

scala> (f(_)).compose(g(_:String))
res22: String => String = <function1>

Could you please explain what's going on, and provide alternative syntaxes to achieve the composition?

Thanks.

Upvotes: 0

Views: 123

Answers (1)

som-snytt
som-snytt

Reputation: 39587

You can see the (unexpected) expansion using magic show comment:

scala> f(_).compose(g(_)) // show
[snip]
      val res0 = ((x$1) => f(x$1).compose(((x$2) => g(x$2))))

Function literals need the params constrained, as you showed. f _ is eta expansion, which is different from f(_) which is sugar for x => f(x).

Since the unintended application f(x$1) returns a string, which is a Int => Char for indexing, you get the added type mismatch.

Underscore is covered by many SO questions, including one canonical.

Upvotes: 2

Related Questions