評価戦略
[Wikipedia|▼Menu]
.mw-parser-output .ambox{border:1px solid #a2a9b1;border-left:10px solid #36c;background-color:#fbfbfb;box-sizing:border-box}.mw-parser-output .ambox+link+.ambox,.mw-parser-output .ambox+link+style+.ambox,.mw-parser-output .ambox+link+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+style+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+link+.ambox{margin-top:-1px}html body.mediawiki .mw-parser-output .ambox.mbox-small-left{margin:4px 1em 4px 0;overflow:hidden;width:238px;border-collapse:collapse;font-size:88%;line-height:1.25em}.mw-parser-output .ambox-speedy{border-left:10px solid #b32424;background-color:#fee7e6}.mw-parser-output .ambox-delete{border-left:10px solid #b32424}.mw-parser-output .ambox-content{border-left:10px solid #f28500}.mw-parser-output .ambox-style{border-left:10px solid #fc3}.mw-parser-output .ambox-move{border-left:10px solid #9932cc}.mw-parser-output .ambox-protection{border-left:10px solid #a2a9b1}.mw-parser-output .ambox .mbox-text{border:none;padding:0.25em 0.5em;width:100%;font-size:90%}.mw-parser-output .ambox .mbox-image{border:none;padding:2px 0 2px 0.5em;text-align:center}.mw-parser-output .ambox .mbox-imageright{border:none;padding:2px 0.5em 2px 0;text-align:center}.mw-parser-output .ambox .mbox-empty-cell{border:none;padding:0;width:1px}.mw-parser-output .ambox .mbox-image-div{width:52px}html.client-js body.skin-minerva .mw-parser-output .mbox-text-span{margin-left:23px!important}@media(min-width:720px){.mw-parser-output .ambox{margin:0 10%}}

出典は列挙するだけでなく、脚注などを用いてどの記述の情報源であるかを明記してください。記事の信頼性向上にご協力をお願いいたします。(2014年9月)

評価戦略(ひょうかせんりゃく、: evaluation strategy)とは、プログラミング言語や、ラムダ計算のようなから成る計算模型において、如何なる手順で、評価すなわち式からを得るか、という(通常決定的な)規則群である。
概要

プログラミング言語では、その意味のうち、サブルーチン呼び出しや演算子式の評価において引数をいつどういう順序で評価し、仮引数は実引数にどう置換されるのか、サブルーチン呼び出しや演算子式の値への置換はどうなのかといったことが、言語仕様によって、あるいは実装によって定義される(あるいは未定義とされる)。

ラムダ計算(など)における評価すなわち簡約(reduction)においては「(1)入れ子状になった式の最も外側から簡約するか、最も内側から簡約するか (2)関数適用の (X Y) という形の式において、X と Y のどちらの簡約を先にするか」という選択肢がある。これは後述する、プログラミング言語における正格評価と非正格評価にほぼ対応し、同じ言葉が使われることもあるが、(プログラミング言語の意味論の議論といった場合を別にして)モデルについての議論と実装についての議論であり、混同するのが望ましくない場合もある。

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

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

正格評価の手続き型言語ないし命令型言語における、if文のような制御の分岐をおこなう構造は、そういった言語の中で一種の非正格評価を実現するものとみなせる。また短絡評価される演算子も同様にみなせる。
正格な評価

正格な評価とは、関数の引数が常にその関数に引き渡される前に完全に評価されることを意味する。

チャーチ符号化(英語版)においては、演算子先行評価は関数の正格な評価に写像される。そのため、正格な評価は「先行評価」とも呼ばれる。多くのプログラミング言語は、関数については正格な評価をする。
作用的順序

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

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

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

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

参照の値渡し (共有呼び: call by sharing、オブジェクト呼び: call by object、call by object-sharing) は Barbara Liskov 他によって1974年にCLU言語で最初に call by sharing と呼ばれた評価戦略である。[2] 日本語では参照の値渡し[3]とも呼ばれる。Python、Iota、JavaRubyJavaScriptSchemeOCamlAppleScript等の多数の言語で使われている。しかしながら「参照の値渡し」という用語は一般的では無く、異なる情報源間で用語の混乱が見られる。例えば、Javaの分野ではJavaは全て値渡しであると言われている。参照の値渡しは、言語上の値がプリミティブ型ではなくオブジェクトに基づいているということ、つまり全ての値が「ボックス化」されていることを意味している。

参照の値渡しの意味論は参照渡しとは異なる: In particular it is not call by value because mutations of arguments performed by the called routine will be visible to the caller. And it is not call by reference because access is not given to the variables of the caller, but merely to certain objects[4](意訳「とりわけ、呼び出し先で行われた引数に対する変更は呼び出し元からも見えるため、値渡しではない。また、アクセスは呼び出し元の変数ではなく、単にあるオブジェクトに対して行われるため、参照渡しでもない。」) だから、例えば、変数が渡されたとき、呼び出し先のスコープ内で変数への代入を装うことは不可能である。ただし、関数は呼び出し元と同じオブジェクト(コピーされたものではない)にアクセスできるため、オブジェクトが可変(ミュータブル)であれば、関数内でのオブジェクトへの変更は呼び出し元にも反映される。これは値渡しの意味論とは異なる動作である。オブジェクトはコピーでもクローンでもない、つまり共有されているから、関数内での可変オブジェクトへの変更は、呼び出し元からも見えると言うことである。例として、配列(Array)が可変であるRubyで書くと:def f(arr) arr.append(1)endm = []f(m)p m

これは [1] を出力する。なぜなら、appendメソッドは呼び出されたオブジェクトを変更しているからだ。

これらの言語では、変数を渡すことは、変数によって参照される実際のオブジェクト渡す(アクセスする)事を意味しており、オリジナルの(呼び出し元の)変数にアクセする事では意味しているわけでは無いため、関数内での代入は呼び出し元に影響を与えない。再束縛された変数(仮引数となる変数)は関数内にしか存在しないため、呼び出しと元の対応する変数(実引数となる変数)は元の束縛を維持する。上記のRubyでの変更の動作と新しいオブジェクトを引数に代入する次のコードを比較してみると:def f(arr) arr = [1]endm = []f(m)p m

これは [] を出力する。なぜなら、arr = [1] という式は、新しい配列を、変数が参照する(つまりはオブジェクトの実体が保存されている)場所ではなく、変数そのものに再代入するからだ。

不変(イミュータブル)オブジェクトでは、オブジェクトの識別が変数そのものである言語を除き、参照の値渡しと値渡しに実質的な違いはない。可変オブジェクトでの参照の値渡しは、入出引数(input/output parameters)に代わるものである: 仮引数は代入せず(引数は上書きせず、オブジェクトの識別は変更しない)に、オブジェクト(引数)を変更する。

この用語は海外のPythonコミュニティ(call by sharingとして)および日本のRubyコミュニティ(参照の値渡しとして)では広く使用されているが、JavaやVisual Basic等の他の言語では同一の意味論でも値渡しとし、この場合の値はオブジェクトへの参照であると記述される場合が多い。
Call by copy-restore

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

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

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

遠隔手続き呼出し (RPC) などで、このようなふるまいが見られることがある。
部分評価詳細は「部分評価」を参照

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


次ページ
記事の検索
おまかせリスト
▼オプションを表示
ブックマーク登録
mixiチェック!
Twitterに投稿
オプション/リンク一覧
話題のニュース
列車運行情報
暇つぶしWikipedia

Size:23 KB
出典: フリー百科事典『ウィキペディア(Wikipedia)
担当:undef