1

Scala では、アンダースコアを使用して単純なマップを作成できます。たとえば、次のように書く代わりに:

def roleCall(people: String*){
  people.toList.map(x => println(x))
}  

...代わりに次のように書くことができます:

def roleCall(people: String*){
  people.toList.map(println(_))
}  

しかし、何らかの理由で私は書くことができません:

def greet(people: String*){
  // This won't compile!
  people.toList.map(println("Hello " + _))
}

代わりに、次のように書く必要があります。

def greet(people: String*){
  people.toList.map(x => println("Hello " + x))
}

誰でも理由を説明できますか?

4

1 に答える 1

1

基本的に、関数定義の簡略構文は、ネストされた括弧がない場合にのみ期待どおりに機能します。これは、ネスト レベルごとに、アンダースコアが存在する独自のスコープが作成されるためです。REPL では、たとえば次のことを確認できます。

scala> val list = List(1,2,3).map(_ + 1)
list: List[Int] = List(2, 3, 4)

scala> val list = List(1,2,3).map((_ + 1))
list: List[Int] = List(2, 3, 4)

どちらも機能しますが、括弧の後に何かを追加すると、エラーが発生します:

val list = List(1,2,3).map((_ + 1) + 1)
<console>:58: error: missing parameter type for expanded function ((x$1) => x$1.$plus(1))
       val list = List(1,2,3).map((_ + 1) + 1)

((x$1) => x$1.$plus(1))ご覧のとおり、エラーは式全体ではなく関数 (_ + 1) (メッセージに示されている) のみに関係する(_ + 1) + 1ため、括弧内の部分は別の関数として扱われ、アンダースコア_はこの範囲で解釈されます。外部関数ではなく、内部関数。

なぜ機能するのかはよくわかりませんList(1,2,3).map(println(_))が、単一の引数のために単なる偶然に機能しているように見えるエッジケースのようです。詳細を教えていただければ幸いです。とにかく、アンダースコアを含む無名関数定義内で括弧を使用すると、遅かれ早かれ問題が発生するため、避ける方がよいでしょう。

于 2014-10-08T22:09:49.360 に答える