rogue-one
rogue-one

Reputation: 11587

Right associative functions with two parameter list

I was looking at the FoldLeft and FoldRight methods and the operator version of the method was extremely peculiar which was something like this (0 /: List.range(1,10))(+). For right associative functions with two parameter lists one would expect the syntax to be something like this((param1)(param2) op HostClass). But here in this case it is of the syntax (param1 op HostClass)(param2). This causes ambiguity with another case where a right associative function returns another function that takes a single parameter. Because of this ambiguity the class compiles but fails when the function call is made as shown below.

class Test() {
val func1:(String => String) = { (in) => in * 2 }    
def `test:`(x:String) = { println(x); func1 }
def `test:`(x:String)(y:String) = { x+" "+y }
}

val test = new Test

(("Foo") `test:` test)("hello")
<console>:10: error: ambiguous reference to overloaded definition,
both method test: in class Test of type (x: String)(y: String)String
and  method test: in class Test of type (x: String)String => String
match argument types (String)
              (("Foo") `test:` test)("hello")

so my questions are

Is this an expected behaviour or is it a bug?

Why the two parameter list right associative function call has been designed the way it is, instead of what I think to be more intuitive syntax of ((param1)(param2) op HostClass)?

Is there a workaround to call either of the overloaded test: function without ambiguity.

Upvotes: 1

Views: 234

Answers (2)

rogue-one
rogue-one

Reputation: 11587

The Scala's Type System considers only the first parameter list of the function for type inference. Hence to uniquely identify one of the overloaded method in a class or object the first parameter list of the method has to be distinct for each of the overloaded definition. This can be demonstrated by the following example.

object Test {
 def test(x:String)(y:Int) = { x+" "+y.toString() }
 def test(x:String)(y:String) = { x+" "+y }
}

Test.test("Hello")(1)
<console>:9: error: ambiguous reference to overloaded definition,
both method test in object Test of type (x: String)(y: String)String
and  method test in object Test of type (x: String)(y: Int)String
match argument types (String)
              Test.test("Hello")(1)

Upvotes: 1

Gregor Ra&#253;man
Gregor Ra&#253;man

Reputation: 3081

Does it really fail at runtime? When I tested it, the class compiles, but the call of the method test: does not.

I think that the problem is not with the operator syntax, but with the fact that you have two overloaded functions, one with just one and the other with two parameter lists.

You will get the same error with the dot-notation:

test.`test:`("Foo")("hello")

If you rename the one-param list function, the ambiguity will be gone and

(("Foo") `test:` test)("hello")

will compile.

Upvotes: 0

Related Questions