匿名遞歸函數貌似仍是有過一段時間流行的,我這兩天本身弄了個lisp,花了很多心思,來回調整完善,這不,暫時告一段落,我也體驗一下吧,咱的lisp git
首先,給出調用lisp的go代碼: github
package main import "github.com/hydra13142/lisp" func main() { console := lisp.NewLisp() // 建立一個執行環境,環境負責保持函數和變量 console.Eval(``) // 執行的lisp語句放入``內 // 下面一句的寫法,能夠讓你從控制檯輸入lisp語句,執行並返回結果 // console.Eval(`(println (scan))`) }
咱們要製做的遞歸函數爲求從1到整數n的全部整數的和 閉包
首先,我很高興的說,咱的lisp那是有個self關鍵字的,這個關鍵字專門用來遞歸調用滴,咱們能夠這樣寫: 函數
(lambda (n) (cond ((> n 0) (+ (self (- n 1)) n) ) (1 0) ) )不過大多數的lisp貌似沒有self或者this關鍵字吧,因此咱們有以下的版本:
(lambda (n) (each (define (f n) (cond ((> n 0) (+ (f (- n 1)) n) ) (1 0) ) ) (f n) ) )
這裏的each意爲順序執行下面的語句,最後一句做爲返回值;而define毫無疑問就是定義了一個函數f(n) oop
不過這是妥妥的耍賴皮啊,雖然看起來是lambda,用起來也是lambda,其實倒是對有名字的函數包裝而已 this
不要着急,咱們還有這一版: lua
( (lambda (f) (f n f) ) (lambda (n t) (cond ((> n 0) (+ n (t (- n 1) t) ) ) (1 0) ) ) 10 )
這一個版本,就使用了額外的參數來交叉調用實現遞歸(話說這個用法在lisp裏簡直是黃金手指) code
可是這樣缺陷就是,一寫出來就是調用的形式,咱們想要一個函數啊,因此修改以後以下: 遞歸
( (lambda (f) (lambda (n) (f n f)) ) (lambda (n t) (cond ((> n 0) (+ n (t (- n 1) t) ) ) (1 0) ) ) )
嗯,咱們接受一個lambda,返回一個lambda,這是閉包,可咱的lisp恰巧就支持閉包 it
固然,lisp很給力的地方就是它的宏系統,這個我也試了,放在(2)裏了。
下面就和遞歸不要緊了;
lisp最讓人不適應的地方,就是它排斥循環(雖然lisp通常仍是提供循環的),下面是個循環版:
(lambda (n) (each (define s 0) (loop (define i 0) (< i n) (each (define i (+ i 1)) (define s (+ s i)) ) ) s ) )固然咱們其實有終極必殺器:
(lambda (n) (/ (* (+ n 1) n) 2) )