重新发明轮子:Node.JS /事件驱动编程与功能编程?

iva*_*ble 19 javascript ajax haskell functional-programming

现在最近有关于Node.JS的炒作,这是一个使用Javascript回调的事件驱动框架.根据我的有限理解,它的主要优点似乎是你不必按顺序一步一步地等待(例如,你可以获取SQL结果,同时调用其他函数).

所以我的问题是:这与CL,Haskell,Clojure等功能语言有什么不同或更好?如果不是更好,那么为什么人们不只是做功能语言(而不是用Javascript重新发明轮子)?

请注意,我没有Node.JS和函数式编程方面的经验.所以一些基本的解释会有所帮助.

Mtn*_*ark 33

通过阅读Node.JS文档(以及漂亮的幻灯片),我认为其他答案在这里缺少关于它的观点:Node.JS是基于我们期望它们阻止的编写程序的风格的想法I/O是错误的,而我们应该启动I/O(例如读取数据库或读取套接字)并传递一个函数来处理I/O的结果以及请求.

所以不要这样做:

var result = db.query("select.."); // blocking
// use result
Run Code Online (Sandbox Code Playgroud)

Node.JS基于这样做的想法:

db.query("select..", function (result) {
    // use result
});
Run Code Online (Sandbox Code Playgroud)

作者(Node.JS)指出,这种编程方式在许多系统中都很笨拙,因为语言没有闭包或匿名函数,而且库主要是阻塞I/O. 但是,Javascript提供前者(并且程序员已经习惯了它如何在浏览器中以类似的方式使用JS),Node.JS填充后者:是一个完全事件驱动的I/O库,没有阻塞调用一点都不

这与函数式编程有何关系?所有函数式编程语言都提供了足够强大的闭包构造,可以完成Node.JS尝试使用Javascript的功能.大多数都使代码更容易编码,因为传递闭包通常是语言的基础.

至于Haskell,使用Monads,这种事情可以很容易构建.例如:

doQuery :: DBConnection -> IO ()
doQuery db = do
    rows <- query db "select..."
    doSomething rows
    doSomethingElse rows
Run Code Online (Sandbox Code Playgroud)

这些非常顺序,命令式的代码行实际上是IOmonad 控制下的一系列闭包.好像在JavaScript中你写过:

db.query("select...", function (rows) {
    doSomething(rows, function () {
        doSomethingElse(rows, function () { /* done */ })
    })
})
Run Code Online (Sandbox Code Playgroud)

本质上,当用函数式语言编写monadic代码时,你已经按照Node.JS作者希望我们编写的形式编写它:顺序计算的每一步都作为一个闭包传递给前一个.但是,看看代码在Haskell中看起来有多好!

此外,您可以轻松使用并发Haskell功能轻松实现此非阻塞操作:

forkQuery :: DBConnection -> IO ThreadId
forkQuery db = forkIO $ do
    rows <- query db "select..."
    doSomething rows
    doSomethingElse rows
Run Code Online (Sandbox Code Playgroud)

不要将它forkIO与您习惯使用的昂贵的进程分支,甚至OS进程线程混淆.它基本上与Node.JS使用的轻量级执行线程相同(只有更丰富的语义).你可以像Node.JS一样拥有1000多个.

所以,简而言之 - 我认为Node.JS正在构建一个存在于JavaScript中的工具,但在函数式语言中更为自然.此外,我认为Node.JS中的所有元素已经存在于Haskell及其包中,然后是一些.对我来说,我只是使用Haskell!


har*_*rms 10

我也不太了解Node.JS,但我真的没有看到它(从你的描述)和函数式编程之间有任何惊人的相似之处.根据您的描述,Node.JS似乎旨在帮助异步编程 - 当您声明"您不必按顺序一步一步地等待"时,您可以执行其他任务,因为一个长时间运行的任务可以完成其任务.

函数式编程与此完全正交 - 即它与异步性没有任何关联.你可以有一个没有另一个,或者两个在一起,或者两者都没有.函数式编程是关于消除程序中的副作用,以及允许函数作为语言的第一类成员,与其他值类似地进行操作和组合.

  • 请注意,我从未声称它确实如此.编程风格本身就是我定义的.关于这一点的争议很少.关于应该允许哪种语言称为"函数式编程语言" - 任何允许该风格的语言,主要关注的是支持该风格的语言,或者只支持其他风格的语言,一直存在争论.这是一场不同的辩论. (3认同)
  • 嗯,说实话,函数式编程并不意味着纯语言.Haskell只是选择这样做. (2认同)