Node.JSドキュメント(と素敵なslide deck)を読んで、私はここで他の答えがそれについてのポイントを見逃していると思います:Node.JSは、我々がそれらを期待するプログラムを書くスタイルI/Oをブロックするのは間違っています。代わりに、I/O(データベースの読み込みやソケットの読み込みなど)を開始し、その要求と共にI/Oの結果を処理する関数を渡す必要があります。
そうではなく、この操作を行います。ノードの著者は、(
db.query("select..", function (result) {
// use result
});
:
var result = db.query("select.."); // blocking
// use result
のNode.jsをこれを行うの考えに基づいています。JS)は、言語がクロージャーや匿名関数を持たず、ライブラリが主にI/Oをブロックしているため、このプログラミング方法は多くのシステムでは非常に扱いにくいと指摘しています。しかし、Javascriptは前者を提供しています(プログラマーはJSがブラウザのようなイベントでどのように使用されているかを前提としています)、Node.JSは後で入力します。ブロッキング呼び出しのない完全イベント駆動のI/Oライブラリまったく。
これは関数型プログラミングとどのように関連していますか?すべての関数型プログラミング言語は、Node.JSがJavascriptで何をしようとしているかを行うのに十分強力なクロージャー構造を提供します。クロージャを渡すことは一般的に言語にとって基本的なものなので、ほとんどの場合、コーディングがさらに簡単になります。
Monadsを使用しているHaskellの場合、この種のものは構築が非常に簡単です。たとえば:
doQuery :: DBConnection -> IO()
doQuery db = do
rows <- query db "select..."
doSomething rows
doSomethingElse rows
コードのこれらの非常にシーケンシャル、不可欠の線は、実際にIO
モナドの制御下で、クロージャのシーケンスです。このJavaScriptであなたが書かれたかのようである:関数型言語でモナドのコードを書くときに本質的に
db.query("select...", function (rows) {
doSomething(rows, function() {
doSomethingElse(rows, function() { /* done */ })
})
})
を、あなたはすでにのNode.jsの作者は私たちが書きたい形でそれを書いている:各ステップ逐次計算のうちの1つは、クロージャとして前の計算に渡される。しかし、コードがHaskellでどれくらいうまく見えるかを見てください!高価なあなたが使用しているプロセスのフォーク、あるいはOSのプロセスとそのforkIO
を混同しないでください
forkQuery :: DBConnection -> IO ThreadId
forkQuery db = forkIO $ do
rows <- query db "select..."
doSomething rows
doSomethingElse rows
:
さらに、あなたは簡単に同時Haskellは簡単にこの非ブロック操作を実現する機能を使用することができますスレッド。これは基本的に、Node.JSが使用している軽量の実行スレッドと同じです(多少意味のあるセマンティクスでのみ)。 Node.JSが目指すのと同じように、1000年代のことができます。
つまり、Node.JSはJavaScriptに存在するファシリティに基づいて構築されていると思いますが、それは関数型言語ではもっと自然です。さらに、私はNode.JSにあるすべての要素がすでにHaskellとそのパッケージに存在していると考えています。私にとって、私はハスケルを使うだけです!
正直言って、機能プログラミングは純粋な言語を意味するものではありません。ハスケルはこれを行うことを選んだだけです。 – codebliss
私はそれを主張したことはないことに注意してください。プログラミングスタイルは、私が定義した通りです。それについての少しの論争。スタイルを許す言語、主な目的がそのスタイルをサポートしている言語、または他のスタイルをサポートしていない言語のみを「関数型プログラミング言語」と呼ぶべきであることについて、進行中の議論があります。それは別の議論です。 – harms