JavaScript需要Blocks

英文出自:yehudakatz.com,编译:CSDN赵红

常常会遇到有人将Ruby的区块(Blocks)看作相当于JavaScript的“first class functions ”的误解。由于传递功能,尤其是当你可以创建匿名的传递功能,这是非常强大的。事实上,JavaScript和Ruby有一个机制使其自然会认为等值。

人们在谈到为什么Ruby的区块不同于Python的函数时,通常会讲到一些关于Ruby和JavaScript的匿名分享,但Python没有。初看之下,一个Ruby区块就是一个“匿名函数”(或俗称一个“封装”),正如JavaScript函数就是其中之一。

作为一个早期的Ruby/JavaScript开发者,无可否认我也有过这样的观点分享。错过一个重要的细节,对结果会产生较大影响。这个原理常被称为“Tennent’s Correspondence Principle”,这条原理说:“For a given expression expr, lambda expr should be equivalent.”这就是被称为抽象的原则,因为这意味着,用“区块”的方法很容易重构通用代码。例如,常见文件资源管理的情况。试想在Ruby中,File.open块形式是不存在的,你会看到以下代码:

乍一看,在Ruby和JavaScript中确实如此。例如,假设你正在使用的文件打印它的mtime。您可以轻松地重构相当于在JavaScript:

到这里:

事实上,这样的情况往往给人错误的印象,Ruby和JavaScript有同样用匿名函数重构常用功能的能力。

不过,再来一个稍微复杂一些的例子。我们首先在Ruby中编写一个简单的类,计算文件的mtime和检索它的正文:

同样地,需要注意的重点是,我们构建区块却并不改变它的内部代码。但不幸的是,这个相同情况的例子无法在JavaScript中正常工作。让我们在JavaScript中来写等同的FileInfo类:

如果我们试图将其转换成一个接受重复函数的代码,那mtime方法看起来将是:在这里有两个非常普遍的问题。首先是上下文改变了。我们可以通过允许绑定第二参数,但这意味着每次重构时需要确认并通过一个变量传递参数,就是说这一情况会在因为缺乏JavaScript信任组件时而出现。

这很烦人,更棘手的还在于,它是从内部返回结果而不是从函数外部。这个真实的结果违反了抽象原则中的对应原理。相反,在函数中用区块方法毫不费力地重构具有相同开始和结束的代码时,JavaScript库作者需要考虑使用者对API处理嵌套函数时进行的一些操作。作为一个JavaScript库资源的编写者和使用者看来,这提供了一个很好的基于区块的API。

迭代和回调

值得注意的是,区块lambda函数接受功能调用的案例包括迭代器、同步与互斥、资源管理(如区块形式的File.open)。

使用函数作为回调时,关键字不再有意义。从一个已经返回的函数返回是什么意思?在这种情况下,通常涉及回调函数lambda表达式做出了很大的意义。在我看来,这解释了为什么JavaScript事件触发代码,涉及了大量的回调。

由于这些问题,ECMA工作组负责的ECMAScript,TC39,正在考虑加入块lambda表达式语言。这将意味着,上面的例子可重构:

TC39并没有实质性改变这个例子,并且要注意区块lambda表达式自动返回他们的最后一个语句。

经验显示,Smalltalk和Ruby不需要理解一种语言可怕的对应原理,满足它获得自己想要的结果。“迭代”概念并不内置到语言,而是被自然块定义的结果。这使得Ruby以及其他常用语言的开发者可建立自定义的丰富、内置的迭代设置。作为一个JavaScript实践者,我经常碰到的情况是,用一个for循环比使用forEach更为简单明了。

业界人士观点

munificent :

In order to have a language with return (and possibly super and other similar keywords) that satisfies the correspondence principle, the language must, like Ruby and Smalltalk before it, have a function lambda and a block lambda. Keywords like return always return from the function lambda, even inside of block lambdas nested inside.In case you want to get your google/wikipedia on, what Katz is talking about here is a “non-local return”.

更多评论详细请点击这里>>

ericbb :Alternate formulation with hypothetical shift/reset (delimited continuation support) and blocks that return

 

It’s the computation within the reset block that comes after the shift form is evaluated。Calling it after returning from the method would not raise an exception.

更多评论详细请点击这里>>

 

收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部