オズで末尾再帰の最適化
-
19-09-2019 - |
質問
怠惰な関数型言語に似て オズは、特定の形態を可能に ある末尾再帰の最適化 一定の厳格な機能的には見られません 標準MLを含む言語、 スキーム、および同時機能 言語Erlangの。しかし、標準 オズでの関数定義ではありません 怠惰ます。
これは、その後に末尾再帰で、次の機能を表示するために行くオズ>
fun {Map Xs F}
case Xs
of nil then nil
[] X|Xr then {F X}|{Map Xr F}
end
end
これは、それがその先頭に機能F
を塗布した後、尾にMap
を呼び出した結果にそれを付加した結果に、空のリストと非空のリストに空のリストをマップするん何。最後の操作は、先頭に追加、ないMap
への再帰呼び出しであるため、他の言語では、これは、末尾再帰ではありません。
だから私の質問は:「オズでの標準関数定義は怠け者ではない」場合は、オズは、スキームやErlangのような言語ではないことを何をするのかのために末尾再帰最適化を実行することができるようにする(あるいはしないのだろうか?)この機能?そして、正確にいつオズの関数末尾再帰のですか?
解決
これは の末尾再帰モジュロCons
のに呼ばれています。基本的には、の先頭追加のリストに直接、のの再帰呼び出しがの添付のと同じです後にリストに直接、のの前に再帰呼び出し(従って、純粋に機能的「ループ」の「副作用」としてリストを構築します)。これは単なるcons
リストが、一定の操作で任意のデータコンストラクタではない作品末尾再帰の一般化したものです。
これは、最初の<のhref = "http://www.cs.indiana.edu/cgi-binにダニエル・P・フリードマンとDavid S.ワイズにより、1974年にLISPのコンパイル技術として説明した(ただし、名前が付けられていない)して/techreports/TRNNN.cgi?trnum=TR19" のrel = 『nofollowを』> のテクニカルレポートTR19:反復<への再帰構造の巻き戻し/ em>のとそれが正式に命名され、1980年にデビッド・HDウォーレンによって導入されました史上初のPrologコンパイラを書くのコンテキストでます。
オズの面白いところは、しかし、TRMCは言語機能も明示的なコンパイラの最適化でもない、それは言語の実行セマンティクスのちょうど副作用だということです。具体的には、オズは、すべての変数は、データフロー変数であることを意味し、宣言同時制約言語(またはすべての保管場所を含め、「すべては約束です」)であるという事実。すべては約束があるので、私たちのように、関数から戻ってモデル化することができます。の最初のの後、約束のように、戻り値、およびを設定するの後にのそれを果たしています。
ピーター・バンロイ、本 の概念、技術の共著者、そしてピーター・ヴァン・ロイとセイフHaridiによって、コンピュータプログラミングののモデルはまた、オズのデザイナーの一人、及びそのimplementatorsの1 を、TRMCはラムダ究極にコメントスレッドでどのように機能するかを正確に説明しています< href = "http://lambda-the-ultimate.org/node/2273#comment-40235" のrel = "nofollowを"> の末尾再帰マップと宣言型のエージェントのの
オズの構文に直接翻訳されたとき、悪いSchemeコードの上記の例では、良い末尾再帰オズコードになります。これは、与えます:
fun {Map F Xs} if Xs==nil then nil else {F Xs.1}|{Map F Xs.2} end end
オズは、シングル割り当て変数を持っているためです。実行を理解するために、我々は(私は明確にするためだけの部分翻訳を与える)オズカーネル言語にこの例を翻訳します:
proc {Map F Xs Ys} if Xs==nil then Ys=nil else local Y Yr in Ys=Y|Yr {F Xs.1 Y} {Map F Xs.2 Yr} end end end
Map
が最初にバインドされていないので、つまり、
Yr
は末尾再帰です。これは、単に巧妙なトリックではありません。それが宣言並行性と宣言型マルチエージェントシステムを可能にするので、それは深刻である。
他のヒント
より完全にミュート(私は怠惰な関数型言語とあまり慣れていないけど、あなたはあなたの質問で機能マップを考える場合、ヒープ内の一時的に不完全な値が許可されている場合、末尾再帰の実装に変換するのは簡単です)一度に一つのコール値ます。
私は、彼らがオズでこの変換について話していることを前提としなければなりません。手でこの最適化を行うために使用Lispersは - すべての値は、この場合にはsetcdr
呼び出された関数が使用される、可変だった - しかし、あなたは、あなたがやっていたかを知る必要がありました。コンピュータは、常にメモリのギガバイトを持っていませんでした。それは手でこれを行うことが正当化された、それは間違いなく、もはやあります。
戻るあなたの質問に、他の近代的な言語は、おそらく自動的にそれをしません。他にどのような違い、それを説明するだろう他の言語に比べて、オズにあるのですか?