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"
}