匿名递归函数貌似还是有过一段时间流行的,我这两天自己弄了个lisp,花了不少心思,来回调整完善,这不,暂时告一段落,我也体验一下吧,咱的lisp
首先,给出调用lisp的go代码:
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)
不过这是妥妥的耍赖皮啊,虽然看起来是lambda,用起来也是lambda,其实却是对有名字的函数包装而已
不要着急,我们还有这一版:
(
(lambda
(f)
(f n f)
)
(lambda
(n t)
(cond
((> n 0)
(+
n
(t (- n 1) t)
)
)
(1 0)
)
)
10
)
这一个版本,就使用了额外的参数来交叉调用实现递归(话说这个用法在lisp里简直是黄金手指)
但是这样缺陷就是,一写出来就是调用的形式,我们想要一个函数啊,所以修改之后如下:
(
(lambda
(f)
(lambda (n) (f n f))
)
(lambda
(n t)
(cond
((> n 0)
(+
n
(t (- n 1) t)
)
)
(1 0)
)
)
)
嗯,我们接受一个lambda,返回一个lambda,这是闭包,可咱的lisp恰巧就支持闭包
当然,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)
)