ここでのコメントディスカッションの結果、Cで関数型プログラミングを学ぶことができるかどうか疑問に思います。
ここでのコメントディスカッションの結果、Cで関数型プログラミングを学ぶことができるかどうか疑問に思います。
回答:
当然のことながら、関数型プログラミングはCで行うことができます。理論的には、関数型プログラミングの原則をCで学ぶこともできますが、この言語では簡単にはできません。
私はあなたがOOPのバックグラウンドを少なくとも持っていると思います。行う場合、Cでポリモーフィズム、ゲッター/セッター、可視性ルールなどを含めてOOPを実行できることを認識しておく必要がありますが、そうすることはかなり困難であり、OOPとCの両方を内部で知る必要があります。引っ張って外します。それはFPとほとんど同じです。
あなたがすべき、(それは彼らが難しい学ぶために作る構文ではありませんそれらのほとんどが驚くほど簡単な構文規則を持っている)、そしてやっていることは関数型プログラミング言語を学ぶ最初で、その後、あなたの新たに獲得知恵はあなたがC.を書く方法に影響を与えてみましょう
リクエストに応じて、FPから学び、C、C ++、Javaなどに適用できるいくつかの事項:
Cをハッキングして、いくつかの機能的な概念を提供できます。
このStackOverflowの質問で、さらに詳しく説明します。しかし、Cで関数型プログラミング(またはその大部分)を実行することは可能であるように見えますが、ハックやコンパイラー拡張など、概念を学ぶための最良の方法ではありません。
関数型プログラミングを実際に学ぶには、Lispとその方言(Clojure、Scheme)、Erlang、Haskellなどの著名な関数型プログラミング言語の1つが最適です。これらのいずれも、関数型プログラミングの考え方で機能する完璧なツールです。 F#は、.Netのバックグラウンドがある場合にも適していますが、厳密には関数型プログラミング言語ではなく、マルチパラダイム言語です。
tdammersのコメントでの注意事項:
実際、LISP、clojure、schemeもマルチパラダイムです。Haskellは、純粋でデフォルトの遅延でありながら、モナディックコンテキストで命令型プログラミングを可能にし、並行処理を幅広くサポートしています。これらはすべて、カプセル化、継承、単一の責任、構成など、OOPの世界で収集された知恵の大部分を実装するメカニズムを備えています。言語が他のパラダイムを許可するかどうかはそれほど重要ではありません。それは、どのパラダイムが言語の出発点を形成するかについてです。
彼らは他のパラダイムを超える関数型プログラミングを奨励するため、Lispとその方言とErlangのは、F#のより良い候補である私の知る限りでは、何tdammersは美しくとして述べ言語の開始点。F#には関数型プログラミングが含まれますが、他のサポートされているパラダイムである命令型プログラミングとooプログラミングよりも推奨されません。
Cで関数型プログラミングのすべての側面を学ぶことはできません。しかし、確実に関数型プログラミングをあらゆる命令型言語から始めることができます。これらの開始ビットは、「プログラミング中に物事を純粋に保つ方法」です。そして、それはまたCを行うことができます。詳細については、このブログ投稿を確認してください-
http://www.johndcook.com/blog/2011/07/24/get-started-functional-programming/
関数型プログラミングは、クロージャーとそのアプリケーションに関するものです。誰かがCの降下クロージャーライブラリを表示できる場合を除き、Cを使用して関数型プログラミングを学ぶことを忘れてください。
関数型プログラミングの基本的な概念は、大まかに言えば、変数バインディングとともに関数をキャプチャするクロージャの概念です。クロージャーの普及に加えて、関数型プログラミングには、再帰的な関数や不変の値の使用(どちらもうまく機能する)など、他にもいくつかの特徴があります。これらの特性は何よりも文化的な問題であり、事実上すべての言語でそれらを使用するための技術的な障害はありません。これが、私の答えでクロージャに焦点を当てている理由です。すべての言語で簡単にクロージャを作成できるわけではありません。
クロージャの典型的な用途は、プライバシーメカニズムの実装です。たとえば、Javascriptコード–例ではJavascriptを選択しました。これは、いわゆる「Cのような構文」を持つ関数型言語であり、あなたの質問はCに精通していることを示唆しているためです。
create_counter = function()
{
var x = 0;
var counter = function()
{
++x;
return x;
};
return counter;
}
次に
a = create_counter();
b = create_counter();
2つの関数がa
あり、b
互いに素なコレクションを数えます。この例の要点は、変数x
は、クロージャーを定義するcounter
クロージャーによってキャプチャされ、そのたびに新しいcounter
クロージャーis instantiated by the function, it gets its fresh own idea of what
x`がキャプチャされるということです。
クロージャのもう1つの一般的な使用法は、関数の部分的なアプリケーションの定義です。syslog
関数の実装と同様のレポート機能があるとします。
var log = function(priority, message) {
…
};
どこの引数priority
とmessage
文字列の一つである第1の一つとして期待されている"debug"
、"info"
と上のようにします。次のようにログファクトリを定義できます。
var logWithPriority = function(priority) {
return function(message) {
log(priority, message);
};
};
それを使用して、ログ機能の特殊なバージョンを定義します。
var debug = logWithPriority("debug");
var info = logWithPriority("info");
…
このfor
ようにエラーが発生しやすいループを作成する代わりに、これは非常に便利です。
for(i = 0; i < journal.length; ++i) {
log("info", journal[i]);
}
より簡潔で、より短く、よりシンプルに記述できます(はありませんがi
、はるかに優れています)。
journal.forEach(logWithPriority("info"));
クロージャの3番目の重要なアプリケーション分野は遅延評価の実装です。特別な言語サポートがより良い実装を提供できることに注意してください。
遅延関数は、直接計算を実行する代わりに、質問を実行するために呼び出す(または遅延の専門用語で「強制する」)ことができるクロージャーを返します。これを行う動機は、計算の準備と計算の実行を分離することです。これの実用的な例は、正規表現のコンパイルです。プログラムが起動時に多くの正規表現をコンパイルする場合、起動するのに多くの時間が必要になります。代わりに、正規表現を遅延コンパイルして、必要に応じて強制的に実行すると、プログラムをすぐに開始できます。もちろん、正規表現は、かなりの初期化時間を必要とする任意の構造で置き換えることができます。
クロージャを使用して遅延評価を実装する方法を次に示します。配列の最大値を返すarrayMax関数の従来の実装を考えてみます。
function arrayMax(array) {
return array.reduce(function(a, b) {
return Math.min(a, b);
};
}
レイジーバリアントは次のようになります。
function arrayMax(array) {
var memo = null;
function actuallyCompute() {
if(memo === null) {
memo = array.reduce(function(a, b) {
return Math.min(a, b);
});
}
return memo;
}
return actuallyCompute;
}
戻り値は、値を計算したり、すでに計算されている場合はもう一度取得したりするために使用できるクロージャーです。
これらの3つの例で、クロージャーとそのアプリケーションが関数型プログラミングの中核であることを確信できます。
関数型プログラミングを学ぶとは、クロージャーを使ってプログラミングする方法を学ぶことです。結果として、関数型プログラミングを研究するための言語を探すときは、クロージャを簡単に操作できる言語、特に関数の部分的な適用を検討する必要があります。逆に、クロージャを簡単に操作できない言語は、適切な選択ではありません。
使用するツールは学習に大きな影響を与えると思います。使用するプログラミング言語が利用する手段を提供していないプログラミング概念を学ぶことはほとんど不可能です。もちろん、常にいくつかのことを学ぶことはできますが、適切に学ぶことはできません。
ので、しかし、それは、学術とにかくあるマルティーニが彼のコメントで述べている、あなたがしても可能性が関数型プログラミングを学ぶ、あなたがすべきことをやろうではない、これはある言語があるので、非常に簡単には。
Cで関数型プログラミングを学ぶべきではありませんが、厳密な関数型言語(Haskell、Caml、Erlangなど)で学びます。
関数型の初心者であれば、非関数型言語を使ってそれを実現することはできません。より可能性が高いのは、関数型プログラミングだと思うことをするように訓練し、間違った方法で物事を学ぶことです。また、物事を正しい方法で「再学習」することは、最初に正しい方法で学ぶよりも常に困難です。
とにかく、Cで汎関数を実行することは、すでに汎関数を知っている人にとっては良い練習だと思います。なぜなら、その人は裏で何が起こっているのか、コンピューターが実際に何をしているかを知るからです。