Scala 下劃線 簡化匿名函式注意事項

2021-10-07 18:08:50 字數 1753 閱讀 7255

eta expansion 的就近expand 解析原則

underscores extend outwards to the closest closing expr: top-level expressions or expressions in parentheses

翻譯:下劃線_ 組成的表示式遇到括號() 或者最頂層表示它就會發生函式的擴充套件eta-expansion

# 使用scala repl 演示

scala <<

'eof'

// 錯誤寫法

list(1, 2, 3).map((_*2)

+1)/

/ _*

2 屬於下劃線表示式,遇到括號它就會轉化為(x)

=>//

((_*2)

+1) 就變成了((x)

=> +1),

// 乙個匿名函式+

1,結果不知道是什麼東西自然報錯

// 正確寫法

list(1,

2,3).map(_*2+

1)//

(_*2+1

) 轉化為(x)

=>

// 正常的匿名函式,函式引數型別根據list 元素推斷為int

// 建議使用正常的匿名函式寫法,避免簡寫解析錯誤

list(1,

2,3).map(x=

>)

// 另外,單個_ 不構成表示式,以下寫法都是正確的,且效果一樣

list(1,

2,3).map(_+1)

list(1,

2,3).map((_)+1

)// 但是_.tostring 就屬於表示式了

list(1,

2,3).foreach(println(_))

// 正常

list(1, 2, 3).foreach(println(_.tostring)) // 報錯

// 原因同上,下劃線表示式(_.tostring) 轉化成了x=>x.tostring 匿名函式

// 而println 只接收string 型別的引數,所以執行報錯

// 退出scala repl

:quit

eof

# 使用scala repl 演示

scala <<

'eof'

// 定義高階函式(普通函式作為其引數)

def ff(f: => unit)

// 錯誤傳入函式

ff(_ + 1) // 報錯

// 下劃線表示式(_ + 1) 會被轉化成((x) => )

// x 的資料型別無法推斷導致報錯,這和集合的map 方法不同

// map 會根據集合元素推斷作為引數的匿名函式的引數型別

list(1, 2, 3).map(_ + 1) // 正常

// 正確傳入函式

ff((x: int) => ) // 正常

// 明確作為引數的匿名函式的引數型別

// 實際上,ff 定義時忽略了引數函式的引數型別

// 即ff 可以接收沒有引數的**塊{}

// 但**塊也是明確告訴高階函式引數函式沒有引數

ff() // 正常

// 只要是明確指出,無論有沒有引數都可以正常執行

// 退出scala repl

:quit

eof

scala 下劃線解析報錯

scala eta-expansion

scala 中 下劃線與星號( )

1.變長引數 例如定義乙個變長引數的方法sum,然後計算1 5的和,可以寫為 scala def sum args int sum args int int scala val s sum 1,2,3,4,5 s int 15但是如果使用這種方式就會報錯 scala val s sum 1 to 5...

核心函式前面單下劃線和雙下劃線

在我們閱讀核心 時,經常會看到有的函式名稱前面會帶有 的雙下劃線,而有些又沒有,這個有什麼用呢?原來核心api函式具有這種名稱的,通常都是一些介面的底層函式,應該謹慎使用。實質上,這裡的雙下劃線就是要告訴程式設計師 謹慎呼叫,後則後果自負。舉個例子,在核心模組的初始函式時,實際的定義如下 stati...

Scala 中下劃線的常見使用

有時候乙個變數的名字或者值並不重要或者並不會被使用,那麼我們可以宣告這個變數 val 100val l 1 to 10 map 100 還有一種情形是在self types中作為型別限制 trait engine trait motor實現motor 時必須要先實現engine。最後,在范型中也會使...