2015-03-31 26 views
1

我在看FoldLeft和FoldRight方法,並且該方法的操作符版本非常奇特,就像這樣(0 /:List.range(1,10))(+)。 對於具有兩個參數列表的右聯合函數,人們可能會認爲語法是這樣的(HostClass((param1)(param2))。 但在這種情況下,它是語法(param1 op HostClass)(param2)。這會導致另一種情況的歧義,即右聯合函數返回另一個接受單個參數的函數。 由於這種不明確性,類會編譯,但在進行函數調用時會失敗,如下所示。正確的關聯函數與兩個參數列表

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") 

所以我的問題是

這是一個預期的行爲或者是一個錯誤嗎?

爲什麼這兩個參數列表正確的關聯函數調用已經被設計出來了,而不是我認爲更直觀的語法((param1)(param2)op HostClass)?

是否有一種解決方法來調用重載測試:函數中沒有任何歧義。

+0

試''DEF測試:'(X:字符串,Y:字符串)= {X +」「+ Y}' – 2015-03-31 08:16:06

回答

1

斯卡拉的類型系統只考慮函數的第一個參數列表進行類型推斷。因此,爲了唯一標識一個類或對象中的一個重載方法,該方法的第一個參數列表對於每個重載定義都必須是不同的。這可以通過以下示例來演示。

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) 
0

它真的在運行時失敗嗎?當我測試它時,班級編譯,但方法test:的調用不。

我認爲問題不在於操作符的語法,而是因爲您有兩個重載函數,一個只有一個,另一個帶有兩個參數列表。

你會得到同樣的錯誤與點符號:

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

如果重命名一個PARAM列表功能,模糊性將消失,

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

將編譯。