web-dev-qa-db-ja.com

関数パラメーターの型と=>

メソッドパラメータの宣言とは正確にはどういう意味ですか。

def myFunc(param: => Int) = param

上の定義の=>の意味は何ですか?

38
PrimosK

これは、いわゆるpass-by-nameです。これは、Intを返す必要がある関数を渡していることを意味しますが、主にパラメーターの遅延評価を実装するために使用されます。それはやや似ています:

_def myFunc(param: () => Int) = param
_

例を示します。いくつかのanswer値を返すInt関数について考えてみましょう。

_def answer = { println("answer"); 40 }
_

そして、2つの関数、1つはIntを取り、もう1つはIntを取りますby-name

_def eagerEval(x: Int)   = { println("eager"); x; }
def lazyEval(x: => Int) = { println("lazy");  x; }
_

次に、answerを使用して両方を実行します。

_eagerEval(answer + 2)
> answer
> eager

lazyEval(answer + 2)
> lazy
> answer
_

最初のケースは明らかです。呼び出す前にeagerEval()answerが評価され、_"answer"_文字列を出力します。 2番目のケースははるかに興味深いものです。実際には、関数をlazyEval()に渡します。 lazyEvalは最初に_"lazy"_を出力し、xパラメータを評価します(実際には、パラメータとして渡されたx関数を呼び出します)。

こちらもご覧ください

57

Scala言語仕様では、用語call-by-nameを使用しています:

値パラメータのタイプは、=>でプレフィックスを付けることができます。 x:=> T。そのようなパラメーターのタイプは、パラメーターのないメソッドタイプ=> Tです。これは、対応する引数が関数の適用時に評価されるのではなく、関数内で使用されるたびに評価されることを示しています。つまり、引数はcall-by-nameを使用して評価されます。

- Scala言語仕様のセクション4.6.1

12

上記のTomasz Nurkiewiczの答えに追加すると、()=> Intと=> Intの間で私が遭遇する違いは、2番目がベアブロックでの呼び出しを許可することです。

scala> def myfunc(f : () => Int ) = println("Evaluated: " + f )
myfunc: (f: () => Int)Unit

scala> def myfunc2(f : => Int ) = println("Evaluated: " + f )
myfunc2: (f: => Int)Unit

scala> myfunc({1})
<console>:9: error: type mismatch;
 found   : Int(1)
 required: () => Int
              myfunc({1})
                  ^

scala> myfunc2({1})
Evaluated: 1
7
mo-seph