吃了大力丸的Ruby:unfold的实现
来源:互联网 发布:招聘软文 知乎 编辑:程序博客网 时间:2024/04/28 16:24
最近奇忙。从早到晚工作。别说写博客,连读博客都 没有时间。虽然一直想八卦一下JavaScript那浓眉大眼的也背叛革命了这件大事,却抽不出空。不过看到这么精彩的代码,还是忍不住转载。
起因是这样的:大家都熟悉fold函数,也就是Ruby里常用的inject()函数:给出起始值,把某个Collection里的值叠加上去。比如说,给出起始值0,累加数组[1, 2, 3, 4, 5]:
[1, 2, 3, 4, 5].inject(0){|sum, n| sum = sum + n}
有了fold,便有相反的unfold:把单个的对象映射到Collection上。比如说
10.unfold { |n| n-1 unless n == 1 }.inspect => [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]10.class.unfold(&:superclass).inspect => [Fixnum, Integer, Numeric, Object]
它的实现也出奇地漂亮:通过递归把unfold调用改写为数组操作。颇有term rewriting系统的风范:
class Object
def unfold &block
block.call(self).unfold(&block).unshift(self)
end
end
class NilClass
def unfold &block
[]
end
end
用例子最容易说明这段实现的惊艳之处。我们手工执行3.unfold{|n| n - 1 unless n ==1}:
- 我们用block指代上式里的{|n| n - 1 unless n == 1}。根据unfold的定义,上式变为block.call(3).unfold(&block).unshift(3)
- 执行block.call(3)得到2,于是我们得到2.unfold(&block).unshift(3)
- 根据定义,我们得到block.call(2).unfold(&block).unshift(2).unshift(3)
- 执行block.call(2),我们得到1.unfold(&block).unshift(2).unshift(3)
- 再根据定义,我们得到block.call(1).unfold(&block).unshift(1).unshift(2).unshift(3)
- block.call(1)的结果是nil,所以我们得到nil.unfold(&block).unshift(1).unshift(2).unshift(3)
- nil早准备好了unfold的定义,于是我们得到[].unshift(1).unshift(2).unshift(3),也就是[3, 2, 1]了。
现在胃口被吊起来的老大们可以看这里的讨论了。
- 吃了大力丸的Ruby:unfold的实现
- 吃了大力丸的Ruby
- 吃了大力丸的Ruby 2
- 以后不该吃的不能吃了。。。
- 吃了耦合的苦头
- 买了一大堆吃的
- 吃一块猪肉的时候你吃了几分“费”
- [爆笑]吃了伟哥的公鸡
- 毕业的散伙饭吃了
- 到吃荔枝的季节了
- 肚子饿了,去找点吃的
- 程序员,到了吃芋头的时候了
- 戴尔吃了联想的豆腐
- 鸟儿吃了我种的草莓
- 吃了没文化的亏
- 我吃了同事的那个包子
- 救命!GNOME"吃"了我的男朋友!
- 今天吃了公司的生日蛋糕
- OpenGL实用开源代码列表
- 掌握 Ajax,第 1 部分: Ajax 简介
- C# 操作INI文件的类(支持中文)
- 如何正确使用SWT控件
- java操作Excel、PDF文件(转)
- 吃了大力丸的Ruby:unfold的实现
- 关于inc文件
- 内存分配 知识,全局,局部,静态变量
- (求助)一个关于ACCESS数据库转化到MYSQL后的处理问题
- C#中常用的经典文件操作方法
- e-Learning课件的销售方式
- 钢丝流-BISU的战斗哲学
- 堆、栈及静态数据区详解
- 使用ICE和STLPort需要注意的事项