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 代碼來表示。這是一個很好的例子:數據和代碼是完美的統一。