最近奇忙。從早到晚工作。別說寫博客,連讀博客都 沒有時間。雖然一直想八卦一下JavaScript那濃眉大眼的也背叛革命了這件大事,卻抽不出空。不過看到這麼精彩的代碼,還是忍不住轉載。
起因是這樣的:大家都熟悉fold函數,也就是Ruby裏常用的inject()函數:給出起始值,把某個Collection裏的值疊加上去。比如說,給出起始值0,累加數組[1, 2, 3, 4, 5]:
[, , , , ].inject(){|| sum = sum + n}
有了fold,便有相反的unfold:把單個的對象映射到Collection上。比如說
.unfold { || n- n == }.inspect => [, , , , , , , , , ] .class.unfold(&).inspect => [, , , ]
它的實現也出奇地漂亮:通過遞歸把unfold調用改寫爲數組操作。頗有term rewriting系統的風範:
&block
block.call().unfold(&block).unshift()
&block
[]
用例子最容易說明這段實現的驚豔之處。我們手工執行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]了。
現在胃口被吊起來的老大們可以看這裏的討論了。