Y 或 Z 組合器
儘管 Julia 不是一種純函式式語言,但它完全支援函數語言程式設計的許多基石:一流函式 ,詞法範圍和閉包 。
定點組合子是在功能的程式設計的關鍵組合子。因為朱莉婭有著急切的評價語義(正如許多函式式語言,包括 Julia 深受啟發的 Scheme),Curry 的原始 Y-combinator 不會開箱即用:
Y(f) = (x -> f(x(x)))(x -> f(x(x)))
然而,Y 組合子 Z-combinator 的近親確實會起作用:
Z(f) = x -> f(Z(f), x)
這個組合器接受一個函式並返回一個函式,當用引數 x
呼叫時,它將自己傳遞給 x
。為什麼函式自身傳遞會有用?這允許遞迴而不實際引用函式的名稱!
fact(f, x) = x == 0 ? 1 : x * f(x)
因此,Z(fact)
成為階乘函式的遞迴實現,儘管在此函式定義中沒有可見的遞迴。 (當然,遞迴在 Z
組合器的定義中很明顯,但這在一種急切的語言中是不可避免的。)我們可以驗證我們的函式確實有效:
julia> Z(fact)(10)
3628800
不僅如此,它的速度與我們對遞迴實現的預期一樣快。LLVM 程式碼演示了將結果編譯為普通舊分支,減去,呼叫和乘法:
julia> @code_llvm Z(fact)(10)
define i64 @"julia_#1_70252"(i64) #0 {
top:
%1 = icmp eq i64 %0, 0
br i1 %1, label %L11, label %L8
L8: ; preds = %top
%2 = add i64 %0, -1
%3 = call i64 @"julia_#1_70060"(i64 %2) #0
%4 = mul i64 %3, %0
br label %L11
L11: ; preds = %top, %L8
%"#temp#.0" = phi i64 [ %4, %L8 ], [ 1, %top ]
ret i64 %"#temp#.0"
}