著作一覧 |
関数のパラメータについて、Call by ValueとCall by Nameの2種類への分類をする場合、この2つの差は、いつ評価するかにある。
Call by Valueは呼び出し時に評価する。
Call by Nameは呼び出し後に評価する。
したがって、この分類をするのであれば、C、Java、C#、Ruby、すべてCall by Valueとなる。
# Pass by ValueとPass by Referenceとは異なる話(日本語の「~渡し」というのはpass byの訳なのだな)
Scalaでは、Call by ValueとCall by Nameは、パラメータの型指定の場所(場所はそうだけど、おそらく、その位置がどの呼び出しかを指定する場所なのだと思う)をどう書くかで決まる。
def fun(x : Int, y => Int)
なら、xはCall by Valueで、yはCall by Nameとなる。
今、上記のfunに対して、fun(1 + 1, 2)、fun(2, 1 + 1)の2つの呼び出しを考える。最初は、呼び出し前に、1+1が評価され2となり、fun(2, 2)として呼び出される(呼び出し前に1評価)。後者は、fun(2, 1 + 1)のまま呼び出される(呼び出し前に評価なし)。
もし、fun(x : Int, y => Int) = x ならば、後者の呼び出しのほうが高速に実行できる(cbvとcbnの差の1つは評価数=実行速度)。
次の関数loopを考える。
def loop() = loop
この関数は無限に再帰するため評価が終了しない。
fun(1, loop)と、fun(loop, 1)がある場合、前者は終了し、後者は終了しない。
もし、cbnがなく、def fun(x: Int, y: Int)としか定義できなければ、loopをいずれの引数としてもfunの呼び出しは行われない(呼び出し前にloopを評価しようとするが終了しないため)。
ジェズイットを見習え |