Ruby 是很强大的语言,有不少高级特性。本文展现了不使用几乎全部特性,只使用 Proc
和 Proc.new
、Proc#call
来编程的奇技淫巧。html
只使用如下特性:git
此外,咱们还使用了常量,这只是为了加强可读性。若是不用常量的话,咱们能够重复书写proc。因此咱们的程序实际上不依赖这个特性。github
Ruby 中的 Proc 支持多参数。实际上,多参数调用能够改写成嵌套的单参数调用。例如:算法
lambda { |x, y| x + y }.call(3, 4)
能够改为编程
lambda { |x| lambda { |y| x + y } }.call(3).call(4)
因为咱们的目标是使用尽量少的特性,因此咱们将代码限定为接受单参数的proc。c#
在 Ruby 中,建立 Proc 有四种写法:segmentfault
Proc.new { |x| x + 1 } proc { |x| x + 1 } lambda { |x| x + 1 } -> x { x + 1 }
它们有一些细微的差异,包括多参数的处理,和return
的对待,因为咱们的代码中不使用这些特性,因此四者是等效的。数组
一样,调用也有四种写法:ruby
p.call(41) p[41] p === 41 p.(41)
这样组合一下,就有16种写法。为了统一,咱们使用以下的写法:ide
-> x { x + 1 }[41]
咱们尝试解决 FizzBuzz问题:
输出0到100的数字,可是3的倍数输出Fizz,5的倍数输出Buzz,同时是3和5的倍数的输出FizzBuzz。
使用 Ruby 有不少种解法,比较直接的是以下的解法:
(1..100).map do |n| if (n % 15).zero? 'FizzBuzz' elsif (n % 3).zero? 'Fizz' elsif (n % 5).zero? 'Buzz' else n.to_s end end
首先,咱们须要在不使用数字的状况下来表示数字。这里的咱们只用到了天然数。
记住,咱们只容许使用建立Proc和调用Proc两个特性。此时咱们须要表示天然数,那么,咱们能够经过调用的次数来表示,即,一次调用表示1,二次调用表示2,三次调用表示3:
ZERO = -> p { -> x { x } } ONE = -> p { -> x { p[x] } } TWO = -> p { -> x { p[p[x]] } } THREE = -> p { -> x { p[p[p[x]]] } }
咱们的代码中须要数字是三、五、1五、100:
THREE = -> p { -> x { p[p[p[x]]] } } FIVE = -> p { -> x { p[p[p[p[p[x]]]]] } } FIFTEEN = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } } HUNDRED = -> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } }
因为if、elsif、else语句能够改写成嵌套的if语句,所以,咱们只要能经过 Proc 实现 if 结构就能够了。
因为咱们只有 Proc 可用,所以咱们必须把 if 结构也表示成 Proc 的形式。咱们能够将 if 视为一个 proc,它接受三个参数,第一个参数为条件语句(布尔值),第二个参数为第一个参数为真时执行的语句,第三个参数为第一个参数为假时执行的语句。
利用上面提到的将多参数 Proc 转为单参数的技巧,咱们的 IF 结构以下:
IF = -> b { -> x { -> y { # b 为真时返回 x,不然返回 y } } }
返回值取决于 b 的真假,不过别忘了,咱们连 Ruby 内建的布尔值都不用!所以,咱们先要实现布尔值。
既然咱们须要实现:
b 为真时返回 x,不然返回 y
那么咱们能够将 b (布尔值)定义为一个 Proc,当它返回 x 时咱们说他是真的,当它返回 y 时咱们说它是假的:
TRUE = -> x { -> y { x } } FALSE = -> x { -> y { y } }
若是你还记得数字 0 的定义的话,你就会发现其实 FALSE 和 0 是等价的。
ZERO = -> p { -> x { x } }
所以咱们的 IF 只需返回 b[x][y]
便可,b
会根据自身的真假返回对应的语句:
IF = -> b { -> x { -> y { b[x][y] } } }
回顾如下上面的定义,IF 经过 IF[b][x][y]
形式调用,接受 b
x
y
三个参数,而后返回 b[x][y]
。也就是说,IF[b][x][y]
和 b[x][y]
是等价的,既然如此,那么 IF 的定义就能够简写:
IF = -> b {b}
而后咱们就能够调用 IF 来实现条件语句:
>> IF[TRUE][:foo][:bar] => :foo >> IF[FALSE][:foo][:bar] => :bar
结合上节的内容,咱们的程序能够改为以下的伪代码:
(ONE..HUNDRED).map do |n| IF[(n % FIFTEEN).zero?][ 'FizzBuzz' ][IF[(n % THREE).zero?][ 'Fizz' ][IF[(n % FIVE).zero?][ 'Buzz' ][ n.to_s ]]] end
固然这只是伪代码,不能实际执行,例如 Ruby 不支持 ONE..HUNDRED
这样的写法。
咱们的程序中有三个余数是否为零的判断。所以咱们须要使用 Proc 实现是否为零的判断。
回顾咱们先前的数字的定义:
ZERO = -> p { -> x { x } } ONE = -> p { -> x { p[x] } } TWO = -> p { -> x { p[p[x]] } } THREE = -> p { -> x { p[p[p[x]]] } } ...
咱们注意到,只有零是直接返回x
而没有调用p
,其余数字都至少调用了一次p
。同时,咱们指望的效果是零返回真,非零返回假。所以,咱们能够将x
设为真,而让p
老是返回假,而后让判断函数返回数字 Proc 返回的值。这样,只有当数字是零的时候,p
才不会被调用,判断函数才会直接返回x
,也就是真。
IS_ZERO = -> n { n[-> x { FALSE }][TRUE] }
由此咱们的伪代码能够修改成:
(ONE..HUNDRED).map do |n| IF[IS_ZERO[n % FIFTEEN]][ 'FizzBuzz' ][IF[IS_ZERO[n % THREE]][ 'Fizz' ][IF[IS_ZERO[n % FIVE]][ 'Buzz' ][ n.to_s ]]] end
而后咱们要实现的就是取余运算。为此咱们先实现最基本的递增、递减运算。
递增运算很简单,首先咱们注意到,n
表明了n次调用p
,即n[p][x]
,那么咱们只要再调用一次便可,p[n[p][x]]
:
INCREMENT = -> n { -> p { -> x { p[n[p][x]] } } }
递减的实现比较复杂:
DECREMENT = -> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }] [-> y { x }][-> y { y }] } } }
篇幅有限,不详细解释递减。能够简单验证一下:当 n 为 1 的时候,直接返回 x,也就是 0。
有了递增、递减以后,咱们很容易就能实现加减,进而实现乘法和乘方:
ADD = -> m { -> n { n[INCREMENT][m] } } SUBTRACT = -> m { -> n { n[DECREMENT][m] } } MULTIPLY = -> m { -> n { n[ADD[m]][ZERO] } } POWER = -> m { -> n { n[MULTIPLY[m]][ONE] } }
回到咱们的取余运算上来,首先,咱们给出标准的取余算法:
def mod(m, n) if n <= m mod(m - n, n) else m end end
首先,咱们须要实现小于等于的判断。判断 n 是否 小于等于 m,只需判断 n -m 是否小于等于零。
咱们已经实现了是否等于零的判断。
同时,因为咱们只实现了天然数,根据咱们的 SUBTRACT 定义,若是一个小数减去一个大数,那么它一样会返回 0。
所以,小于等于的定义以下:
IS_LESS_OR_EQUAL = -> m { -> n { IS_ZERO[SUBTRACT[m][n]] } }
由此咱们获得取余运算的定义:
MOD = -> m { -> n { IF[IS_LESS_OR_EQUAL[n][m]][ MOD[SUBTRACT[m][n]][n] ][ m ] } }
等等,这个定义是有问题的!因为 IF 的参数会先运算再传递,所以调用 MOD 时会先调用参数中的 MOD,而后这个 MOD 又须要递归地调用另外一个 MOD,造成无限的调用。所以,咱们须要延缓参数中的 MOD 的运算。在 Ruby 中,使用 Proc 包裹便可实现延缓运算。
MOD = -> m { -> n { IF[IS_LESS_OR_EQUAL[n][m]][ -> x { MOD[SUBTRACT[m][n]][n][x] } ][ m ] } }
不过这里有个缺陷。咱们这里递归地调用了 MOD,在 MOD 的定义中包含了 MOD,这其实是使用了赋值语句了,而不是常量定义了。
好在,不使用赋值语句(也就是匿名函数)也彻底能够实现递归。
若是咱们将 MOD 自身做为参数传入,就能够不依赖赋值语句而递归调用 MOD 自身了。也就是说,咱们须要将 f(x) 改写为 g(f(x)),同时保证 g(f(x)) 和 f(x) 是等效的。
咱们能够手工构造符合条件的 g,不过其实有一个通用的 Y 组合子,对于任意 Proc f,都知足 Y(f(x)) 等价于 f(x):
Y = -> f { -> x { f[x[x]] } [-> x { f[x[x]] }] }
一样,为了延迟运算,咱们须要使用 Y 组合子的变体 Z 组合子:
Z = -> f { -> x { f[-> y { x[x][y] }] } [-> x { f[-> y { x[x][y] }] }] }
关于 Y 组合子和 Z 组合子的推导,能够参考 The Little Schemer
MOD = Z[-> f { -> m { -> n { IF[IS_LESS_OR_EQUAL[n][m]][ -> x { f[SUBTRACT[m][n]][n][x] } ][ m ] } } }]
由此,咱们的程序能够改成:
(ONE..HUNDRED).map do |n| IF[IS_ZERO[MOD[n][FIFTEEN]]][ 'FizzBuzz' ][IF[IS_ZERO[MOD[n][THREE]]][ 'Fizz' ][IF[IS_ZERO[MOD[n][FIVE]]][ 'Buzz' ][ n.to_s ]]] end
要支持 ..
和 map
,咱们须要实现列表。
牢记咱们只有 Proc。考虑到 Proc 接受的一组参数,其实就能够当作列表。那么,反过来咱们也能够用 Proc 接受的参数来表示列表。
咱们先考虑最简单的情形,只有两个元素的列表:(一样使用嵌套的单参数 Proc 来表示多参数)
PAIR = -> x { -> y { -> f { f[x][y] } } } LEFT = -> p { p[-> x { -> y { x } } ] } RIGHT = -> p { p[-> x { -> y { y } } ] }
咱们能够将多元素的列表使用嵌套的 pair 来表示。
此外,为了方便查询列表是否为空,咱们将列表的首个元素做为标记(TRUE 和 FALSE)。
所以, IS_EMPTY
和 LEFT
就等价了。
咱们将空表定义为:
EMPTY = PAIR[TRUE][TRUE]
而在列表前添加元素使用以下 Proc 定义
UNSHIFT = -> l { -> x { PAIR[FALSE][PAIR[x][l]] } }
构造列表的例子:
>> my_list = UNSHIFT[ UNSHIFT[ UNSHIFT[EMPTY][THREE] ][TWO] ][ONE]
..
咱们经过 RANGE Proc 来实现:
def range(m, n) if m <= n range(m + 1, n).unshift(m) else [] end end
这显然是个递归结构,所以咱们一样使用 Y 组合子改写:
RANGE = Z[-> f { -> m { -> n { IF[IS_LESS_OR_EQUAL[m][n]][ -> x { UNSHIFT[f[INCREMENT[m]][n]][m][x] } ][ EMPTY ] } } }]
为了实现#map
,咱们首先实现 FOLD。FOLD相似 Ruby 中的Enumerable#inject
。
既然要实现 FOLD,首先须要实现 FIRST 和 REST:
FIRST = -> l { LEFT[RIGHT[l]] } REST = -> l { RIGHT[RIGHT[l]] }
注意,因为咱们用首个元素表示是否为空列表,所以不能直接使用LEFT
和RIGHT
做FIRST
和REST
使用。
而后实现FOLD:
FOLD = Z[-> f { -> l { -> x { -> g { IF[IS_EMPTY[l]][ x ][ -> y { g[f[REST[l]][x][g]][FIRST[l]][y] } ] } } } }]
实现了 FOLD 以后,map
就能很容易地实现了。
MAP = -> k { -> f { FOLD[k][EMPTY][ -> l { -> x { UNSHIFT[l][f[x]] } } ] } }
好了,用 RANGE 和 MAP 替换一下,咱们的程序基本上就差很少了,只剩下字符串了:
MAP[RANGE[ONE][HUNDRED]][-> n { IF[IS_ZERO[MOD[n][FIFTEEN]]][ 'FizzBuzz' ][IF[IS_ZERO[MOD[n][THREE]]][ 'Fizz' ][IF[IS_ZERO[MOD[n][FIVE]]][ 'Buzz' ][ n.to_s ]]] }]
字符串是由字符组成的。所以咱们能够把字符串当作字符的列表,而后咱们只需实现字符就能够了。
字符串能够编码为数字。FIZZBUZZ 中只用到了0-九、B、F、I、Z、U这些字符,所以咱们偷懒实现一个只支持这些字符的集合:
TEN = MULTIPLY[TWO][FIVE] B = TEN F = INCREMENT[B] I = INCREMENT[F] U = INCREMENT[I] ZED = INCREMENT[U]
咱们使用10-14来表示这五个字符,0-9保留,用于表示数字的字符。
咱们用 ZED 表示 Z,这是由于 Z 已经被咱们用来表示 Z 组合子了。
有了字符以后,字符串就直接用列表表示了:
FIZZ = UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[EMPTY][ZED]][ZED]][I]][F] BUZZ = UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[EMPTY][ZED]][ZED]][U]][B] FIZZBUZZ = UNSHIFT[UNSHIFT[UNSHIFT[UNSHIFT[BUZZ][ZED]][ZED]][I]][F]
剩下的惟一没有实现的就是 FIxnum#to_s
方法了。要实现改方法,咱们须要:
转化为列表,咱们只需递归地除以 10 便可:
def to_digits(n) previous_digits = if n < 10 [] else to_digits(n / 10) end previous_digits.push(n % 10) end
咱们尚未实现<
,不过这里能够用 n <= 9
来代替。而后咱们须要实现 PUSH 和 DIV
PUSH 和 UNSHIFT 很接近,只有位置的差异。为了在尾部添加元素,咱们能够先将该元素添加到一个空表中,而后在设法在这个新列表的前部加上原列表:
PUSH = -> l { -> x { FOLD[l][UNSHIFT[EMPTY][x]][UNSHIFT] } }
除法的实现是基于减法,计算须要减多少次才能减到小于除数:
DIV = Z[-> f { -> m { -> n { IF[IS_LESS_OR_EQUAL[n][m]][ -> x { INCREMENT[f[SUBTRACT[m][n]][n]][x] } ][ ZERO ] } } }]
基于以上两个 Proc,咱们能够有:
TO_DIGITS = Z[-> f { -> n { PUSH[ IF[IS_LESS_OR_EQUAL[n][DECREMENT[TEN]]][ EMPTY ][ -> x { f[DIV[n][TEN]][x] } ] ][MOD[n][TEN]] } }]
利用咱们前面的成果,咱们达成了目标!
MAP[RANGE[ONE][HUNDRED]][-> n { IF[IS_ZERO[MOD[n][FIFTEEN]]][ FIZZBUZZ ][IF[IS_ZERO[MOD[n][THREE]]][ FIZZ ][IF[IS_ZERO[MOD[n][FIVE]]][ BUZZ ][ TO_DIGITS[n] ]]] }]
注意,常数定义仅仅是为了可读性,咱们彻底能够不使用常数:
-> k { -> f { -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> l { -> x { -> g { -> b { b }[-> p { p[-> x { -> y { x } } ] }[l]][x][-> y { g[f[-> l { -> p { p[-> x { -> y { y } } ] }[-> p { p[-> x { -> y { y } } ] }[l]] }[l]][x][g]][-> l { -> p { p[-> x { -> y { x } } ] }[-> p { p[-> x { -> y { y } } ] }[l]] }[l]][y] }] } } } }][k][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> l { -> x { -> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[l][f[x]] } }] } }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]] } }[m][n]][-> x { -> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[f[-> n { -> p { -> x { p[n[p][x]] } } }[m]][n]][m][x] }][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]] } } }][-> p { -> x { p[x] } }][-> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } }]][-> n { -> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]][n][x] } ][m] } } }][n][-> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[x]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> n { -> l { -> x { -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> l { -> x { -> g { -> b { b }[-> p { p[-> x { -> y { x } }] }[l]][x][-> y { g[f[-> l { -> p { p[-> x { -> y { y } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][x][g]][-> l { -> p { p[-> x { -> y { x } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][y] }] } } } }][l][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][x]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }] } }[-> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]] } }[n][-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> x { f[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]] } }[n][m]][-> x { -> n { -> p { -> x { p[n[p][x]] } } }[f[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]][n]][x] }][-> p { -> x { x } }] } } }][n][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][x] }]][-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> f { -> x { n[-> g { -> h { h[g[f]] } }][-> y { x }][-> y { y }] } } }][m] } }[m][n]][n][x] }][m] } } }][n][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]] } }][n]]]] }]
太美了!
只使用Proc.new
和Proc#call
看起来限制太大,不过最终咱们发现它可以构造任何算法!
上面的数据类型彻底使用 Proc 代码来表示。这是一个很好的例子:数据和代码是完美的统一。