LoginSignup
6
3

More than 5 years have passed since last update.

正格評価と遅延評価のイメージ

Posted at

正格評価と遅延評価のイメージ

関数の評価の違いを授業で聞いて、分かりやすかったから忘れないようにまとめておきます。
正格評価を C++、遅延評価を Haskell のコードで説明していきます。

正格評価

簡単に言うと、値を使うか使わないか考えず渡されたら評価する事です。

a.cpp
#include <iostream>
using namespace std;

int foo(int a, int b) {
    return a;
}

int bar(int a) {
    return bar(a - 1);
}

int main(int argc, const char* argv[]) {
    cout << foo( 2, bar(1) ) << '\n';
}

上のプログラムは main 関数で foo 関数を呼んでいます。foo 関数は第一引数の a を返すだけなので b は必要無いです。しかし、正格評価 をする言語では b の値も先に計算しようとします。bar 関数 は終了条件が無い再帰関数なので b の値を計算できないです。従って、このプログラムはセグメントエラーかプログラムが終了しないです。

実行結果
$ g++ a.cpp
$  ./a.out
Segmentation fault

$ g++ -O2 a.cpp
$ ./a.out

最適化オプションをつけないでコンパイルすると、プログラムに割り当てられたスタック領域をドンドン使うので、セグメントエラーが起きます。オプションをつけるとスタック領域を増やさないようにするので、セグメントエラーは起きないです。

遅延評価

簡単に言うと、変数が使われた時に初めて値を計算しようとする評価の事です。

a.hs
foo a b = a
bar a   = bar (a - 1)
main    = do
        print ( foo 2 (bar 1) )

関数は先ほどの C++ のコードと同じです。
しかしHaskell では、遅延評価 をするのでちゃんとプログラムは終わります。

実行結果
$ ghc a.hs
$ ./a
2
6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3