Racket中使用Y組合子

2022-10-10 09:45:09 字數 1988 閱讀 5405

關於y組合子,網上已經介紹很多了,其作用主要是解決匿名lambda的遞迴呼叫自己。

首先我們來看直觀的遞迴lambda定義,

假設要定義階乘的lambda表達,c#中需要這麼定義

func fact = null

;fact = x => x <= 1 ? 1 : x * fact(x - 1);

這種方法非常簡單直接,當然問題也存在,因為這裡fact其實是乙個委託物件,當這個物件改變後,可能就得不到階乘的效果了。

在scala中則是這樣,

def f: int => int = (n:int) => if(n == 0) 1 else  n* f(n - 1)

嗯,在本文的主打語言racket中,則變成這樣

(define f

(lambda (n) (

if (equal? n 0

)

1(* n (f (- n

1))))))

由於這個函式f定義中使用了f自身,那麼如何修改可以去掉這個f?

現在變化一下,增加乙個函式引數f,以使的我們呼叫f時,可以把自身傳遞進去,那樣就解決了前面f的定義中使用了f自身的問題,修好後如下

(define ff

(lambda (f) (lambda (n) (

if (equal? n 0

)

1(* n ((f f) (- n

1)))))))

這樣呼叫((ff ff) 5)就能得到120這個結果了。

當然這裡我們甚至可以不用define這個關鍵字來給這個lambda定義乙個名字,直接上lambda本體,如下

(((lambda (f) (lambda (n) (if (equal? n 0

)

1(* n ((f f) (- n

1))))))

(lambda (f) (lambda (n) (

if (equal? n 0

)

1(* n ((f f) (- n

1))))))) 5)

同意可以得到正確結果120。

y組合子

y = λf. (λx. f (x x)) (λx. f (x x))

一種使用racket的表示為

(define y

(lambda (f) ((lambda (x) (f (lambda (y) ((x x) y))))

(lambda (x) (f (lambda (y) ((x x) y)))))))

這樣,階乘的lambda表示為

(define fact

(y (lambda (f) (lambda (n) (

if (equal? n 0

)

1(* n (f (- n 1))))))))

斐波那契的lambda表示為

(define fib

(y (lambda (f) (lambda (n) (

if (< n 3

)

1(+ (f (- n 1)) (f (- n 2))))))))

這裡,關鍵點在於,y的引數為乙個函式,比如階乘中是

(lambda (f) (lambda (n) (if (equal? n 0

)

1(* n (f (- n 1))))))

這個表示式中可以用f表示自身。

sql server中使用組合索引需要注意的地方

一 使用組合索引需要注意的地方 1 索引應該建在選擇性高的字段上 鍵值唯一的記錄數 總記錄條數 選擇性越高索引的效果越好 價值越大,唯一索引的選擇性最高 2 組合索引中字段的順序,選擇性越高的字段排在最前面 如果把低選擇性的列放在最左端,可能會造成無法使用該索引的情況。3 where條件中包含兩個選...

Lambda演算 簡述Y組合子的作用

y組合子 f.x.f xx x.f xx 接受乙個函式,返回乙個高階函式 y組合子用於生成匿名遞迴函式。什麼叫匿名遞迴函式,考慮以下c語言遞迴函式 int sum int n 這個函式在內部遞迴呼叫了自身,呼叫自身需要函式本體的名字,這個函式叫sum,sum內部用名字sum,遞迴呼叫了自己 在lam...

yum對應ubuntu Ubuntu使用yum

yum介紹 安裝首先開啟終端 ctrl alt t 進入root模式 jerry是使用者名稱,也就是你自己起的名字。是分割的符號 jerry virtualbox是主機名,也就是你所使用的機器的名稱 是當前目錄,表示根目錄 是提示符,當進入root時,會變成 第一種方式 sudo 暫時的 輸入sud...