Scala には、1 つのメソッドが複数のメソッドを取ることができるパラメーター リストの概念があります。ただし、便宜上、端末の空のパラメーター リストを省略できるようにもなっています。そう
f
f()
f()()
すべて同じものかもしれません - を見るまでわかりませんf
。名前指定パラメーターの役割は、コード ブロックの実行を遅らせることです。さて、正式に
def f0: String = "salmon"
def f1(): String = "herring"
def f2()(): String = "halibut"
f0
次に、関数に変換された場合、名前によるパラメーターと一致することを期待し、他のパラメーターは一致しないことを期待します。具体的には、
f0 <==> => String
f1 <==> () => String
f2 <==> () => () => String
変換したとき。経由でリクエストしたときに実際に何が起こるか見てみましょうf _
:
scala> f0 _
res4: () => String = <function0>
scala> f1 _
res5: () => String = <function0>
scala> f2 _
res6: () => () => String = <function0>
しかたがない; f0
実際には、0 ではなく 1 つの空のパラメーター ブロックを持つ関数に変換されます (これは、名前によるパラメーターのように見えます)。したがって、名前によるパラメーターがメソッドを関数にまったく変換していないことがわかります-型シグネチャが一致しません!
代わりに、次のような理由があります。
// I need a code block that returns a long
nanoTime // Wait, there is no nanoTime exactly
nanoTime() // Aha, that works! Must have meant that
: => { nanoTime() } // There, nicely packaged.
違いが見られない理由は、 a を返すためLong
に、 by-name パラメーターが欠落している をすでに埋めている()
が、後で実行するためにすべてをコード ブロックにラップしているためです。
(また、名前によるパラメーターは実際には内部にあることに注意してください。つまりFunction0
、実際にあり、「ゼロ パラメーター ブロック」は単なるコンパイラのフィクションです。実際には、すべてのパラメーター ブロックはコンパイラのフィクションです。つまり、JVM です。単一のパラメータ リストについてのみ知っている. そして、観察された動作をもたらすのは、このノーブロック フィクションと、空の括弧を気にするフィクションとの組み合わせです.)x: => A
x: () => A
空のパラメーター ブロックから関数を要求すると、次のように機能します。
def printF(f: () => String) = println(f())
scala> printF(f0)
<console>:23: error: type mismatch;
found : String
required: () => String
printF(f0)
^
scala> printF(f1)
herring
scala> printF(f2)
<console>:23: error: type mismatch;
found : () => String
required: String
printF(f2)
scala> printF(f2())
halibut
コンパイラはメソッドのシグネチャを関数のシグネチャに一致させようとしているため、括弧が重要になります。名前によるパラメーター状況の特殊なケースは適用されなくなりました。