2011-01-28 59 views
6

時,我不明白爲什麼下面的代碼不會編譯:省略點鏈接調用

class Abc 
{ 
    def b (x : String) = x + "abc" 

    def a (y : String) = 
    { 
     val ls : List[String] = y.lines toList 
     b (ls.head) 
    } 
} 

Main.scala:8:錯誤:類型不匹配; 發現:java.lang.String中 需要的:int B(ls.head)

當我改變 「y.lines toList」 到

y.lines.toList 

或甚至

y.lines toList; 

它確實編譯。

也許編譯器能像

(y.lines).toList(b (ls.head)) 

或類似的東西,但我還是不明白的規則。

+0

你可以在REPL中插入你的語句'(y.lines).toList(b(ls.head)) '(嗯,也許你這樣做了嗎?)來驗證錯誤消息是否相同。那麼 - 我做到了,事實上,它是。 :) – 2011-01-28 03:04:27

回答

1

這並不明顯,它是Scala快捷方式語法和列表索引的組合。如果你想有一個提示,嘗試重新定義b到:

def b(x : String) = 0 

你會得到一些其他的編譯器的垃圾回來,但錯誤會發生變化。簡而言之,Scala編譯器會讓你省略零參數或單參數方法的零部件和點,並且我們知道b看起來像是以某種方式獲得鏈接。蹭的是Scala也使用parens進行列表索引,因此toList返回一個迭代器,可能需要一個參數作爲列表索引。我完全不確定這一部分,但看起來像一旦你開始省略點號,詞法分析器就會變得貪婪,當它遇到一個可能需要一個參數的方法時,會嘗試將下一個語句傳遞給它。在這種情況下,這是一個字符串,因此會引發語法錯誤。

1

你得到它發現與此:

(y.lines).toList(b (ls.head)) 

隨着唯一可能的修正之中:

(y.lines).toList(b).apply(ls.head) 

我不知道這會斯卡拉在這種特殊情況下決定。

粗略地說,該規則是object (method parameters)* [method]。編譯器將繼續,只要它找到有效表達式的標記。 A ;完成表達,並且)}也將完成。如果下一行是空白,表達式也結束。如果下一行以保留關鍵字(valdefif等)開頭,則表達式也會結束。