I am working on DSL for an experimental library that I create in Scala, and I came across some unpleasant features of Scala type output, as it relates to lambda expression arguments that don't seem to be discussed in Scala's Programming book.
In my library, I have the Effect [-T] property, which is used to represent temporary modifiers that can be applied to an object of type T. I have an myEffects object that has a method called + = that takes an argument of type Effect [PlayerCharacter] . Finally, I have a general method when [T], which is used to construct conditional effects, taking a conditional expression and another effect as an argument. The signature is as follows:
def when[T](condition : T => Boolean) (effect : Effect[T]) : Effect[T]
When I call the when method with the specified signature, passing the result to the + = method, it cannot infer the type of the argument in the lambda expression.
myEffects += when(_.hpLow()) (applyModifierEffect) //<-- Compiler error
If I combine the when arguments into a single parameter list, Scala is able to infer the type of the lambda expression simply.
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T] /* Snip */ myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
It also works if I completely remove the second parameter.
def when[T](condition : T => Boolean) : Effect[T] /* Snip */ myEffects += when(_.hpLow()) //This works too!
However, for aesthetic reasons, I really want the arguments to be passed to the when method as separate parameter lists.
My understanding from section 16.10 Programming in Scala is that the compiler first checks to see if the type of the method is known, and if so, it uses this to output the expected types of arguments. In this case, the external method call is + =, which takes an argument of type Effect [PlayerCharacter]. Since the return type when [T] is the Effect [T] and the method to which the result is passed expects an argument of type Effect [PlayerCharacter], he can conclude that T is PlayerCharacter, and therefore the lambda expression type is passed as the first argument " when "is PlayerCharacter => Boolean. This seems to work when arguments are provided in one parameter list, so why breaking arguments in two parameter lists breaks it?