Chinaunix

标题: ruby扫盲之block [打印本页]

作者: zuerrong    时间: 2010-11-18 14:44
标题: ruby扫盲之block
ruby的block其实就是匿名函数(或C里的函数指针)。
在ruby里,方法大量使用block作为参数,看起来很酷,写起来也很高效。

例如,对这么一个数组:

x = [3,1,4,2,9,0]

想要找出所有小于3的成员,那么大家通常会想到数组的select方法:

z = x.select {|s| s <3}

select方法接受一个block为参数。
那么select具体是如何执行这个block的呢?其实秘密就在于ruby的yield这个方法,它用来执行block。


例如,咱们自己可以写一个myfind方法来代替select:
  1. class Array
  2.     def myfind
  3.        if block_given?
  4.            z = []
  5.            each {|s| z << s if yield s}
  6.            z
  7.        else
  8.            raise "no block given"
  9.        end
  10.     end
  11. end
复制代码
我们首先打开Array类(记住ruby的所有类都是开放的),然后定义myfind函数(def myfind)。
如果有block参数传给myfind,那么执行each {|s| z << s if yield s}这句,表示遍历self数组,把每一个元素作为参数传给yield。
然后yield就执行用户传入的block,并判断执行结果。如果为真就把元素压入z数组,最后返回z数组。

如果没有block传给myfind方法,会raise一个运行时错误,说明"no block given"。


OK 让我们看完整脚本:
  1. x = [3,1,4,2,9,0]

  2. class Array
  3.     def myfind
  4.        if block_given?
  5.            z = []
  6.            each {|s| z << s if yield s}
  7.            z
  8.        else
  9.            raise "no block given"
  10.        end
  11.     end
  12. end

  13. z = x.myfind {|s| s < 3}
  14. p z
复制代码
运行结果为:

$ ruby block.rb
[1, 2, 0]
作者: 2gua    时间: 2010-11-27 11:28
这一系列的Ruby帖的出处在哪儿呀?
作者: zuerrong    时间: 2010-11-29 09:22
这一系列的Ruby帖的出处在哪儿呀?
2gua 发表于 2010-11-27 11:28



    我自己写的哦。。
作者: ziyiu123    时间: 2011-02-22 18:54
几个问题:

1.block_given? 这个是从哪里来的? 我怎么ri不到?
2.each {|s| z << s if yield s}  中的each,是不是就是self.each,我试了一下结果一样,但是不敢确定,还请lz赐教。
3.楼主男女?
作者: gr33n    时间: 2011-11-17 02:59
感觉不错,看起来很酷。
作者: 塞图宝    时间: 2014-03-25 07:25
回复 4# ziyiu123


    同问这个
作者: rubyish    时间: 2014-03-26 03:47
本帖最后由 rubyish 于 2014-04-03 01:36 编辑

  
作者: rubyish    时间: 2014-03-26 03:53
本帖最后由 rubyish 于 2014-04-03 01:37 编辑

太感谢了。
作者: 塞图宝    时间: 2014-03-26 06:44
回复 8# rubyish


    :wink: {:3_189:}
作者: dorodaloo    时间: 2015-12-29 11:48
个人感觉不错之扫盲




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2