言語実装の観点から見た関数型言語の違い
-
13-09-2019 - |
質問
「関数型プログラミング」というまったく新しいパラダイムがあり、手続き型プログラミングと比較して思考パターンを完全に変える必要があります。これは、命令型言語やオブジェクト指向言語では通常見られない高階関数、純度、モナドなどを使用します。
私の質問は、どのようにして 実装 これらの言語は、メモリ管理やポインタなどの内部構造などの点で、命令型言語やオブジェクト指向言語とは異なります。
JVM 上で実行される関数型言語があります。これは、これらの言語が JVM 上の他の言語と同様に内部的に動作することを意味しますか?
解決
関数型プログラミング言語の実装では、幅広い実装手法が使用されます。この本には、Scheme (Lisp 方言) の実装への優れた入門書が記載されています。 Lisp を細かく分割する クリスチャン・クイネック著。
他のヒント
関数型言語から生じたコードを使用すると、非機能言語で種々の程度にご覧多くの機能を使用しています。ガベージコレクションは、一般的な使用法に合格しています。末尾呼び出しの最適化は、 GCCとVC ++ の中で行われていますます。
クロージャは、しかし、関数型プログラミングの顕著な特徴です。あなたは他のないものは表示されません。あなたは純粋な関数型言語のみを参照するには、「関数型言語」を定義した場合、両者は同義ではない、あなたは、関数型プログラミングをサポートする命令型言語でクロージャを見つけると(機能的パラダイムはほとんど何ですが、技術的に不可欠である例えばJavascriptとスキーム(中古))。クロージャはコールスタックのためのスパゲッティスタックを持つ場合、またはローカル変数をコピーすることによって実装されるかもしれませんヒープ上のローカル変数を割り当て、ガベージコレクションは、それらの世話をさせることにより、スタックフレームを終了、またはます。
あなたはクロージャを持っていたら、無名関数が比較的容易である(通訳で、彼らは本当に簡単です)。コンパイラで、関数はコンパイル時にバイトコードに変換され、バイトコード(むしろ、エントリ・ポイントのアドレス)は、現在の環境と、実行時に関連している。
機能組成物は、匿名関数に依存することができます。コンパイラは関数合成演算子f . g
に遭遇すると、それは他の引数として1の結果を渡して、二つの引数のf
とg
を呼び出す無名関数を作成します。
モナドは、オブジェクト指向言語で実装することができ、彼らはちょうど彼らが純粋な関数型言語であるとして、必要に応じてではないです。 I / Oモナドは、彼らはちょうどプラットフォームの基礎となる彼は、副作用を可能にするという事実に依存している、あまりにも何か特別なことではありません。
私が頭に浮かぶ1は、関数型言語に特別な注意の恩恵を受ける多くの側面があると思います
関数型言語は再帰たくさん使います。だから、任意の実装は、このケースを最適化しようとする必要があります。例えば。末尾再帰を識別し、内部ループに変換(これスタック保存/復元のような関数呼び出しのオーバーヘッドを節約します)。 ( http://en.wikipedia.org/wiki/Tail_recursion の)
などHaskellのような関数型プログラミング言語の実装は、多くの場合、命令型言語のものとは非常に異なっています。あなたは<のhref =「http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/index.htm」のrel = "nofollowをやって約一つの方法を読むことができますnoreferrer ">ここを。紙は、いくつかの歳にもかかわらず、私はアイデアがまだ使用されていると信じています。
頭に浮かぶの最大の違いは、関数型言語のソースコードは、脱糖<なるように設計される傾向があるということです/>数学的にシンプルかつパワフルな中間言語へ。この言語は、通常、ラムダ、関数呼び出しが含まれている/他の場合、マシン・タイプ、let
のようなもの、そしてより多くのではない全体の多く。変換コードが深く、冗長ではなく、現実的に人間が読めるネストされています。表面的な構文を捨てされます。
このような言語のコンパイラは、まともなコードを生成するために、いくつかのインライン化といくつかの閉鎖最適化を行う必要があります。 (私にはこれらのベースラインの閉鎖の最適化は、自明でないように見える - 分析を逃れるなど - 。しかし、それだけで親しみの欠如かもしれません)。
すべては、すべてが内部的に同じですので、限り、あなたは十分に深く行くと、同じプロセッサ上で実行されます(したがって、同じアセンブリ命令)。
@outis:言語はそれらをサポートするかもしれないが、閉鎖という副作用が行うのと同じ方法で、関数の数学的概念との競合は:彼らはあなたが同じ引数が異なる結果を得ることができます。それはクロージャ手続きではなく、機能的になります。
と、グローバルオーバークロージャを好む(特にコンパイラの実装のコンテキストで)効率の引数があります。 [しかし、私は「仕事のそっくりサイトを」実装することができていても、直接クロージャを提供していない関数型言語を知っている。
(ただし、カリー化がクロージャと同様であり、この競合の影響を受けない、実際に関数型言語で日常的に存在する。)
とにかく、私の意見では、関数型プログラミング言語は、彼らが数学関数であるかのように計算を表現でき作るために大きな努力をする言語です。これは、最適化が機能を最適化で傾斜していることを意味します。
仮に、少なくとも、関数型言語は、純粋に手続き的なアプローチのために有用であろうよりも、マシンが深い抽象化で作業することができます。