コンテンツにスキップ

「評価戦略」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
とりあえず半分ぐらい、大幅に改修
残りもざっと
8行目: 8行目:

評価戦略は、関数の引数をどう扱うかによって、[[#正格な評価|正格]] (strict) な評価戦略と[[#正格でない評価|非正格]] (non-strict) な評価戦略に大きく分類される。

評価戦略は、関数の引数をどう扱うかによって、[[#正格な評価|正格]] (strict) な評価戦略と[[#正格でない評価|非正格]] (non-strict) な評価戦略に大きく分類される。



プログラミング言語によっては、複数の評価戦略を場合により選べるものもある。例えば[[C++]]は、値渡しが基本だが、そのように指定することで参照渡しにもできる。

プログラミング言語によっては、複数の評価戦略を場合により選べるものもある。例えば[[C++]]は、値呼びが基本だが、そのように指定することで参照呼びにもできる。




[[|]][[|]][[if]][[|]][[]]

[[|]][[|]][[if]][[|]][[]]
18行目: 18行目:


=== 作用的順序 ===

=== 作用的順序 ===

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

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



=== 値呼び ===

=== 値呼び ===

26行目: 26行目:


=== 参照呼び ===

=== 参照呼び ===


call by reference: pass by reference[[:en:Aliasing (computing)]][[ALGOL]] name replacement[[Pascal]]

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



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

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




'''[[C]][[ ()|]]Call-by-AddressC++CJavaJavaScript'''

'''[[C]][[ ()|]]call byaddressC++CJavaJavaScript'''C & 


=== Call by copy-restore ===

=== Call by copy-restore ===

51行目: 51行目:


=== 正規順序 ===

=== 正規順序 ===

正規順序の評価<ref>訳は、和田によるSICPの訳書による</ref>(normal-order evaluation)も、もっぱら[[プログラミング言語]]よりは[[計算模型]]で使われる用語で、最も外側の簡約可能な式を簡約する評価戦略であり、関数の引数を評価する前に関数を適用する。プログラミング言語における名前渡しに同じとされることも多いが、英語版Wikipediaでは、名前渡しでは適用されない関数の本体内までは評価しない点が異なるとしている。

正規順序の評価<ref>訳は、和田によるSICPの訳書による</ref>(normal-order evaluation)も、もっぱら[[プログラミング言語]]よりは[[計算模型]]で使われる用語で、最も外側の簡約可能な式を簡約する評価戦略であり、関数の引数を評価する前に関数を適用する。プログラミング言語における名前呼びに同じとされることも多いが、英語版Wikipediaでは、名前呼びでは適用されない関数の本体内までは評価しない点が異なるとしている。



=== 名前渡し ===

=== 名前呼び ===

名前渡し(Call-by-Name)評価では、関数の引数は全く評価されず、捕獲回避置換(Capture-Avoiding Substitution)を使って関数本体内に直接置換される。引数がその関数の評価で使われていない場合、その引数は全く評価されない。引数が複数回使われている場合、その度に再評価される。

名前呼び(call by name、名前渡し: pass by name)では、関数の引数は全く評価されず、捕獲回避置換(Capture-Avoiding Substitution)を使って関数本体内に直接置換される。引数がその関数の評価で使われていない場合、その引数は全く評価されない。引数が複数回使われている場合、その度に再評価される。



渡しはその引数が全く使われていなくとも必ず評価するため、名前渡しの方が好ましいとする考え方もある。しかし、引数が使われている場合は名前渡しの方が性能が悪いという批判もある。

呼びはその引数が全く使われていなくとも必ず評価するため、名前呼びの方が好ましいとする考え方もある。しかし、引数が使われている場合は名前呼びの方が性能が悪いという批判もある。




使[[ALGOL|ALGOL 60]] 

[[ALGOL|ALGOL 60]] 


副作用のある言語における名前呼びには微妙なところがあり、[[:en:Jensen's Device]] のような例が知られている。

=== 必要渡し ===

必要渡し(Call-by-Need)とは名前渡しを[[メモ化]]したもので、関数の引数が評価されると、その値がそれ以降の利用のために代替として格納される。副作用がない場合、これは名前渡しと同じ結果となる。引数が何度も使われている場合、必要渡しの方が性能がよい。



=== 必要呼び ===

必要渡しを使っている言語では、[[モナド (プログラミング)|モナド]]などを使う場合以外では計算の副作用をサポートしない。これによって、遅延評価以前に変数の値が変更されることによる予期しない振る舞いを防ぐ。

必要呼び(call by need、必要渡し pass by need)とは名前呼びを[[メモ化]]したようなもので、関数の引数が評価されると、その値がそれ以降の利用のために代替として格納される。副作用がない場合、これは名前呼びと同じ結果となる。引数が何度も使われている場合、(更新に要するコストの合計が毎回計算するコストの合計より小さければ)必要呼びの方が性能がよい。



これは一種の[[遅延評価]]である。

[[遅延評価]]を引数の評価戦略として見た場合は必要呼びである、と言える。



必要渡しを使っている言語としては[[Haskell]]が有名である。

必要呼びの言語としては[[Haskell]]が有名である。



=== マクロ展開渡し ===

=== マクロ展開呼び ===


Call-by-Macro-Expansion使使{{|Hygienic|en|Hygienic macro}}

call bymacro expansion使使{{|Hygienic|en|Hygienic macro}}


== 非決定性の戦略 ==

== 非決定性の戦略 ==

76行目: 76行目:

完全β-簡約(full β-reduction)においては、任意の時点で任意の関数適用が簡約される(関数の引数を捕獲回避置換を使った関数に置換する)。これは、適用されない関数の本体内でも行われる。

完全β-簡約(full β-reduction)においては、任意の時点で任意の関数適用が簡約される(関数の引数を捕獲回避置換を使った関数に置換する)。これは、適用されない関数の本体内でも行われる。



=== 未来渡し ===

=== 未来呼び ===

未来渡し(Call-by-Future)あるいは並列名前渡し(Parallel Call-by-Name)は必要渡しに似ているが、関数の引数は(必要に応じてではなく)関数本体と並行して(別スレッドで)評価される。関数本体で引数を使用するときにスレッドの同期が行われる。引数が全く使われない場合、引数の評価をしているスレッドは中断され捨てられる。

未来呼び(call by future)あるいは並列名前呼び(parallel call by name)は必要呼びに似ているが、関数の引数は(必要に応じてではなく)関数本体と並行して(別スレッドで)評価される。関数本体で引数を使用するときにスレッドの同期が行われる。引数が全く使われない場合、引数の評価をしているスレッドは中断され捨てられる。



=== 楽観的評価 ===

=== 楽観的評価 ===

楽観的評価(Optimistic Eveluation)は必要渡しの変形の1つであり、関数の引数はある回数だけ部分評価される(回数は実行時に調整される)。そして、評価は中断され、必要渡しで関数が適用される。この方法では必要渡しの性能低下を防ぎつつ、停止属性を保持する。

楽観的評価(Optimistic Eveluation)は必要呼びの変形の1つであり、関数の引数はある回数だけ部分評価される(回数は実行時に調整される)。そして、評価は中断され、必要呼びで関数が適用される。この方法では必要呼びの性能低下を防ぎつつ、停止属性を保持する。



== 注 ==

== 注 ==


2013年10月10日 (木) 03:40時点における版


: Evaluation strategy




reduction(1) (2) (X Y) XY使

 (strict)  (non-strict) 

C++

if






[1]applicative-order evaluation使applynormal-order evaluationWikipedia


call by value: pass by value



call by reference: pass by referenceen:Aliasing (computing)Pascal



Ccall by addressC++CJavaJavaScriptC & 

Call by copy-restore


Call by copy-restore

 call by copy-restore 1



RPC

部分評価




使

使


[2]normal-order evaluation使Wikipedia


call by name: pass by nameCapture-Avoiding Substitution使使使

使使

ALGOL 60 

en:Jensen's Device 


call by need pass by need使



Haskell


call by macro expansion使使Hygienic

β-


β-full β-reduction使


call by futureparallel call by name使使


Optimistic Eveluation1調

  1. ^ 訳は、和田によるSICPの訳書による
  2. ^ 訳は、和田によるSICPの訳書による

関連項目

参考文献