正格評価

提供: MonoBook
移動: 案内検索

正格評価とは、関数引数が常にその関数に引き渡される前に完全に評価されることをいう。 対義語は「遅延評価」である。

概要[編集]

正格な評価とは、関数サブルーチン引数が常にその関数に引き渡される前に完全に評価されることを意味する。 むかしながらの多くのプログラミング言語は関数については正格な評価を行う。

チャーチ符号化においては演算子先行評価は関数の正格な評価に写像される。そのため正格な評価は「先行評価」とも呼ばれる。

作用的順序[編集]

作用的順序の評価[1](applicative-order evaluation)は、もっぱらプログラミング言語よりは計算模型で使われる用語で、まず引数を全て評価し、それに関数をapply(作用、ないし適用)するという方法である。正規順序の評価(normal-order evaluation)の逆として対になっている。プログラミング言語における値呼びに同じとされることも多いが、英語版Wikipediaでは、関数の引数を左から右に後順に走査して簡約可能な式を簡約していく評価戦略で「値呼びとは異なり、関数を作用させる以前に可能な限り関数本体内の項数を減らそうとする」ものとしている。

値呼び[編集]

値呼び(call by value、値渡し: pass by value)は多くの言語で採用されている典型的な評価戦略である。値呼びでは、関数呼び出しにある実引数を評価し、関数の仮引数を新しい変数としてその値に束縛し、しかる後に関数本体を実行する。関数の中で仮引数である変数に値を代入しても、それは局所的なコピーへの代入であり、呼び出した側の変数には影響しない。

手続き型言語ないし命令型言語では、演算子の左辺と右辺や、複数個並んだ引数の評価順が左から右であるか右から左であるかは、結果に違いを齎すことがあるが、仕様で決めている言語もあれば、決めていない言語もある。

参照呼び[編集]

参照呼び(call by reference、参照渡し: pass by reference)では、仮引数が実引数そのもの、すなわちエイリアスになる。実引数は左辺値を持たねばならない(Pascalのように実引数を変数に限定した言語もある)か、左辺値を持たない式の場合は呼び出し側で一時的オブジェクトを構築する言語もある。

仮引数の変数は実引数のエイリアスであるから、それへの代入は呼び出した側の変数にも影響する。これを、ミュータブルオブジェクトがある多くの言語において、オブジェクトへの「参照の値渡し」を行い、オブジェクトを変化させた場合に、呼び出した側から見てオブジェクトの変化が見えることと大変しばしば混同される。

関数の引数として参照を値渡しすることを参照渡しと呼ぶこともあり、C言語のようにポインタを持つ言語では参照呼びではなく「アドレス呼び(call by address)」と呼ぶこともある、と考える者もいるようだが間違いである。C++ではなくCJavaJavaScriptなどの値呼びしかない言語には参照呼びは無く、「それらの言語において似たように見えるもの」を「参照呼び」と呼ぶのは間違いである。間違った説明をネットに掲載したり、さらには書籍にまでする者が後を絶たず、非常に広範に流布しているが間違いである。C言語では、アドレス演算子 & により変数のアドレスを渡すことができるので、呼び先で元の変数の中身を変えてしまうことができるが、値呼びであることに変わりはない。

Call by copy-restore[編集]

Call by copy-restore(複製呼びの結果返し、などと意訳される)は、参照呼びの特殊な実装とも見ることができる。実引数の値が値呼びと同様にコピーされるが、関数呼び出しから戻る時に仮引数の変数の値が、あたかも参照呼びされたかのように書き戻される。

参照呼びと異なるのは、ある call by copy-restore の関数呼び出しの複数の引数に同じ変数を渡した場合、参照呼びでは、引数の1つを更新すると他の引数の内容も更新されるが、こちらでは、それぞれが異なるコピーであるため、他の引数の内容が更新されない。呼び出し側に戻ったときにどうなるかはそれぞれの仕様ないし実装による。

他にも、再帰呼び出しを行ったり、マルチスレッド環境で他のスレッドから観察されたりした場合には結果が異なってくる場合がある。

RPCなどで、このようなふるまいが見られることがある。

部分評価[編集]

部分評価は評価戦略というよりは最適化手法である。部分評価では、適用されていない関数の本体内で評価が継続される。束縛されていない変数を含まない部分式は評価され、引数が既知の関数適用は簡約される。副作用があると、部分評価は予期しない結果を引き起こす可能性がある。このため、部分評価は関数内の副作用を持たない純粋な式についてのみ実施されることが多い。

関連項目[編集]

参考文献[編集]