我本身的lisp,也來實現個匿名遞歸函數玩玩,嘿!

匿名遞歸函數貌似仍是有過一段時間流行的,我這兩天本身弄了個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)
)
相關文章
相關標籤/搜索