2

I'm having a hard time understanding the scala compiler here. I'm passing three higher order functions to a superclass like this:

... extends Arithmetic(Math.pow(-_,_), Math.log(_)/Math.log(_), Math.pow(_,_))

The first function doesn't compile, the last function compiles, the only difference being the minus sign. The compiler gives the following warning:

error: wrong number of parameters; expected = 2

which is confusing, as there are two underscores. I will probably have to ditch the underscore syntax, but I want to understand why this happens. I have also tried

Math.pow(0-(_),_)    Math.pow(0.-(_),_)    Math.pow(0.0.-(_),_)

which all give the same error. Finally

Math.pow(-(_:Double),_:Double)

gives a new error

error: type mismatch;
  found   : Double => Double
  required: Double

which looks more like an actual error instead of me violating syntax. Now my next thought was, "apparently the underscore syntax doesn't work if there are functions within others". But looking at the second function Math.log(_) / Math.log(_), which to my knowledge is converted to Math.log(_)./(Math.log(_)), and compiles, this makes no sense, as here the partially applied log function is passed into ./(...)

Also, the expected type of the function, defined in the superclass Arithmetic is (Double,Double) => Double, so why does the type problem only surface after I explicitely declared the types?

Color me confused.

4
  • 1
    See my answer here for some discussion. Commented May 3, 2014 at 20:33
  • it's even a problem for calls of arity one: var f1: Function1[Double,Double] = _ will allow f1 = Math.sqrt(_) * 3 but f1 = Math.sqrt(_ * 3) gives error: missing parameter type for expanded function ((x$1) => x$1.$times(3)) (though f1 = x => Math.sqrt(x * 3) works just fine) Commented May 3, 2014 at 20:52
  • @RobStarling val f: Double => Double = math sqrt _ * 3. Commented May 3, 2014 at 21:02
  • Travis could have added that this is a dupe. Instead of the close mechanism, SO should aggregate dupes to maximize chances of a search succeeding, then redirect to the most correct answer. Commented May 3, 2014 at 21:04

1 Answer 1

1

Math.pow(_,_) means (x,y) => Math.pow(x,y) whereas Math.pow(-_,_) means y => Math.pow(x => -x,y). Math.log(_)/Math.log(_) is an infix method call, it means the same as Math.log(_)./(Math.log(_)) and therefore (x,y) => Math.log(x)./(Math.log(y)).

See the StackOverflow Scala Tutorial in Chapter 21 "Functions/Function literals" and the subpoints "Placeholder syntax" to find more detailed explanations about how the underscores are parsed.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, but wouldn't Math.log(_)/Math.log(_) then mean y => Math.log(y)./(x => Math.log(x)) by the same logic? Why does this work?
It works because it is infix notation. See my update.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.