首页 > 学院 > 开发设计 > 正文

深入理解Ruby中的block概念

2019-10-26 19:26:22
字体:
来源:转载
供稿:网友

Ruby 里的 block一般翻译成代码块,block 刚开始看上去有点奇怪,因为很多语言里面没有这样的东西。事实上它还不错。
First-class function and Higher-order function

First-class function 和 Higher-order function 是函数式编程语言里面的概念,听起来好像很高端的样子,其实很很简单的。

First-class functions 是指在某些语言里,函数是一等公民,可以把函数当做参数传递,
可以返回一个函数,可以把函数赋值个一个变量等等,反正就是正常值能做的事函数都能做。JavaScript 就是这样的。举个例子(下面的所有例子里,当我提到
JavaScript 时,示例代码都用的 CoffeeScript):

greet = (name) -> return -> console.log "Hello, #{name}"greetToMike = greet("Mike")greetToMike() # => 输出 "Hello, Mike"a = greetToMikea() # => 输出 "Hello, Mike"

在上面的第四行里,greet("Mike") 返回了一个函数,所以第五行里才可以调用 greetToMike()输出"Hello, Mike"。第六行把一个函数赋值给了a,所以第七行就可以调用这个函数了。

higher-order function 一般翻译成高阶函数,是指接受函数做参数或者返回函数的函数。
举个非常常用的例子(用 JavaScript):

a = [ "a", "b", "c", "d" ]a.map((x) -> x + '!') #=> ["a!", "b!", "c!", "d!"]

上面例子里 map 就接受了一个匿名函数作为参数。Array.prototype里的很多方法,比如reduce, filter,every, some 等等都是高阶函数,因为他们都接受函数作为参数。

高阶函数非常强大,表达力很强,可以避免大量重复代码。总的来说,它就是个好东西。
Block 的本质

先来看一组 Ruby 和 CoffeeScript 代码的对比。

a = [ "a", "b", "c", "d" ]a.map { |x| x + "!" } # => ["a!", "b!", "c!", "d!"]a.reduce { |acc, x| acc + x} # => "abcd"a = [ "a", "b", "c", "d" ]a.map((x) -> x + '!') # => ["a!", "b!", "c!", "d!"]a.reduce((acc, x) -> acc + x) # => "abcd"

这两组代码真的看起来超级像。我觉得这也暴露了 Ruby 的 block 的本质:高阶函数的函数参数的变体。

JavaScript 里面的map 函数接受一个函数作为参数,但是 Ruby 里的 map 却接受一个
block 作为参数。

其实 matz 早在一本书里《松本行弘的程序世界》里说了:

代码如下:    最终来看,块到底是什么?
    ...
    块也可以看作只是高阶函数的一种特殊形式的语法。
    ...
    高阶函数和块的本质一样
    ...

在 Ruby 里,函数不是一等公民,没有 first-class functions。但是在 Ruby
里怎样使用高阶函数呢?答案就是使用 block。可以直接用 block,也可以用 lambda

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表