Прочитав документы Node.JS (и хороший slide deck), я думаю, что другие ответы здесь не имеют смысла: Node.JS основан на идее, что стиль написания программ там, где мы их ожидаем для блокировки ввода-вывода является неправильным, и вместо этого мы должны инициировать ввод-вывод (например, чтение базы данных или чтение сокета) и передать функцию для обработки результата ввода-вывода вместе с запросом.
Так что вместо этого:
var result = db.query("select.."); // blocking
// use result
Node.js основан на идее сделать это:
db.query("select..", function (result) {
// use result
});
Авторов (из узла.JS) указывают, что этот способ программирования очень неудобен во многих системах, поскольку языки не имеют замыканий или анонимных функций, а библиотеки в основном блокируют ввод-вывод. Тем не менее, Javascript поставляет первый (и для него используются программисты, учитывая, как JS используется как событие в браузере), а Node.JS заполняется позже: это полностью управляемая событиями библиотека ввода-вывода без блокировки вызовов вообще.
Как это связано с функциональным программированием? Все языки функционального программирования предоставляют конструкции закрытия, достаточно мощные, чтобы делать то, что Node.JS пытается сделать с Javascript. Большинство из них упрощают кодирование, поскольку прохождение закрытия обычно имеет фундаментальное значение для языка.
Что касается Haskell, используя Monads, такого рода вещи можно было бы очень легко построить. Например:
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 авторы хотят, чтобы написать: Где каждый шаг последовательного вычисления передается как замыкание предыдущего. Однако посмотрите, насколько приятнее этот код в Haskell!
Кроме того, вы можете легко использовать одновременно Haskell особенность для достижения этих неблокируемых операций легко:
forkQuery :: DBConnection -> IO ThreadId
forkQuery db = forkIO $ do
rows <- query db "select..."
doSomething rows
doSomethingElse rows
Не путайте, что forkIO
с дорогой вилкой процесса вы привыкли, или даже процесс OS потоки. Это в основном тот же самый легкий поток выполнения, который использует Node.JS (только с несколько более богатой семантикой). У вас может быть 1000 таких, как Node.JS.
Итак, вкратце - я думаю, что Node.JS строится на объекте, который существует в JavaScript, но это гораздо более естественно на функциональных языках. Кроме того, я думаю, что все элементы, которые находятся в Node.JS, уже существуют в Haskell и его пакетах, а затем некоторые. Для меня я просто использовал Haskell!
Ну, если честно, функциональное программирование не подразумевает чистый язык. Хаскелл просто решает это сделать. – codebliss
Заметьте, что я никогда не утверждал, что это так. Стиль программирования сам по себе является таким, каким я его определял. Немного споров об этом. Продолжается дискуссия о том, что нужно называть «функциональным языком программирования» - любым языком, который допускает стиль, любой язык, на котором основной упор поддерживает этот стиль, или только языки, которые не поддерживают никакой другой стиль. Это разные дебаты. – harms