
無為的程式設計
|
179
述語
我們的下一件工作是將
Fixnum#zero?
替換成能以 proc 為基礎的數值一起運作的 proc 為
基礎的實作物。Ruby 值的
#zero?
底層演算法有點像這樣:
def zero?(n)
if n == 0
true
else
false
end
end
(雖然這比必要的更為冗長,但它卻很清楚發生了什麼事:將數值和
0
進行比較;如果
相等就傳回
true
;否則就傳回
false
)
我們要如何改寫這個才能處理 proc(而非 Ruby 數值)?再看一次我們的數值實作物:
ZERO = -> p { -> x { x } }
ONE = -> p { -> x { p[x] } }
TWO = -> p { -> x { p[p[x]] } }
THREE = -> p { -> x { p[p[p[x]]] } }
⋮
請注意,
ZERO
是唯一不呼叫
p
的數值(它只傳回
x
),而所有其他數值至少呼叫一次
p
。
我們可以利用這一點:如果我們以
TRUE
作為它第 2 個引數來呼叫未知的數值,如果數
值為零,它將立即傳回
TRUE
。如果不是零,那麼它會傳回呼叫
p
的任何傳回值,所以如
果我們讓
p
是永遠傳回
FALSE
的 proc,就能如願得到我們想要的行為:
def zero?(proc)
proc[-> x { FALSE }][TRUE]
end
再次強調,將它重寫成 proc 真的很容易:
IS_ZERO = -> n { n[-> x { FALSE }][TRUE] }
我們可以在主控台使用 ...