2012-07-03 30 views
4

據我所知,在斯卡拉管道符的使用應相當於一個方法的調用。所以:斯卡拉「一」 + _.toString沒有表現得像「一個」。+(_。的toString)

scala> "a" + 3.toString 
res0: java.lang.String = a3 

是一樣的:

scala> "a".+(3.toString) 
res1: java.lang.String = a3 

我碰到這個地方沒有發生,當有一個佔位符的時機來了。我正在做更復雜的東西,但它可以蒸餾到:

scala> def x(f:(Int)=>String) = f(3) 
x: (f: Int => String)String 
scala> x("a" + _.toString) 
res3: String = a3 

到目前爲止好。但...

scala> x("a".+(_.toString)) 
<console>:9: error: missing parameter type for expanded function ((x$1) => x$1.toString) 
      x("a".+(_.toString)) 

這裏有什麼區別?我錯過了什麼?

霍爾迪

+2

的[斯卡拉的foreach奇怪的行爲(http://stackoverflow.com/questions/2173373/scala-foreach-strange-behaviour) – sschaef

+5

那麼可能重複, _answer_是重複的,但是怎麼會有人知道這個問題呢?我認爲這個問題的答案應該把相關的問題聯繫起來,而不是關閉問題本身。 –

回答

11

_佔位符只能出現在其功能最上面Expr。這意味着

(_.toString) 

本身是一個函數,"a" + some function of unknown type對編譯器沒有多大意義。

+0

謝謝!所以我明白你是否可以使用_取決於你想表達的表達方式。我可以過濾用col.filter整數的集合(_ + 2 * 3 <10),但我不能做col.filter((_ + 2)* 3 <10),原因(_ + 2)將是一個功能本身。所以,在第二個例子中,我需要重寫它不使用括號o不使用_。 –

10

你中綴表示法的評估是正確的,但你的佔位符參數的理解是錯誤的。

當您使用下劃線作爲一個佔位符參數,你正在創建一個功能。問題是這個函數的邊界是什麼:它從哪裏開始,它在哪裏結束?例如,考慮以下表達式:

_ + _ + _ 

應該如何翻譯?以下是一些備選:

(x, y, z) => { x + y + z } 
(x, y) => { (z) => { x + y } + z } 
(x) => { x + { (y, z) => y + z } } 

好,Scala的規則是,範圍最裏面的括號分隔的表達,或整個表達式除外。因此,在實踐中,你寫了兩個不同的東西:

x("a" + _.toString) // is the same thing as 
x((y) => "a" + y.toString) 

x("a".+(_.toString)) // is the same thing as 
x("a".+((y) => y.toString)) 
+0

非常感謝您的回答! 但我發現令人驚訝的是,它依賴於括號,而不是取決於產生的AST。我使用的兩個表達式都使用相同的AST。 但_的行爲取決於括號。這使我困惑。 –

+0

@ user1207633它顯然不是一樣的AST,因爲它甚至不用相同的方式解析。看看語法 - 在語言規範中有一個EBNF。 –