1957年,Fortran诞生了,这是世界上第一个高级语言。
但是不知道是不是巧合,Fortran诞生仅一年,一个更加新的语言诞生了,这是世界上第二个高级语言,但这个语言越传越玄乎,不仅是麻省理工教学计算机科学的第一个语言,甚至被誉为“上帝的编程语言”。
在GNU 幽默合集中,刊载了一首诗,以下是一些摘抄和翻译:
Lisp的绿意漫过叶片
分形花朵吐出递归的根
当雪花裂解成唯一方程
四字真言刻入永恒…
诸神通晓所有语言
却为每片羽毛预留归途
三十二位的枷锁怎能丈量
沙粒在Lisp中重获自由万物皆在括号里生长
别在磁盘寻找创世日志
当闪电劈开愚昧的字符
六日神迹闪耀Lisp的光泽是的,上帝也有死线
所以他写下——
万物归λ
因此这个语言来头不小,我便虔诚的尝试了一下。
选择方言和解释器
Lisp到现在有67年了,必然产生各种各样的方言,每个方言还有很多版本的解释器,因此可以选择的余地非常繁杂:
但是目前只有两种比较流行的方言:Common Lisp和Scheme,这篇文章我选择了Scheme方言,并且选择了gauche编译器。
Common Lisp和Scheme有什么不同呢?个人认为,Common Lisp和Scheme,就像狮子和家犬。狮子更加强大,难以驯服;家犬更加小巧,容易驯服。而选择哪一种,取决于实际需要。鉴于郝同学只是需要学习一下函数式编程的思想,所以Scheme足够了。
万物皆函数
在Lisp中,每个东西都是函数,都是有返回值的表达式,而单个函数被括号包围,这叫做原子。
例如,想要计算1+1等于几,要这么写:
(+ 1 1)
其中,+
是要将参数输入进去的函数,两个1
就是参数,整个函数被括号包围。
函数式编程
我之前尝试过Haskell,函数式编程大概可以总结成这样:
- 变量不可变。
- 使用递归代替循环。
- 函数不得有副作用。
- 函数除了参数,不得被其它因素干扰输出。
真不知道这种情况下还怎么做项目,毕竟太麻烦了,可能是给计算机科学家看的吧(?
但是谢天谢地的是,Lisp没有Haskell做的那么严格,比如(do)
函数同样可以实现循环,(set!)
函数也可以强制改变变量值。
但这不属于最佳实践,因此在这篇文章中还是会尽量选择函数式编程的写法。
真正的解释型语言
通常解释性语言都会在运行前做一遍预检查,如果出现明显的语法错误或命名错误,都会直接抛出异常。
但这个语言不会做这种预检查,只会检查正在运行的一行,所以我觉得Lisp更像解释型语言。
极为超前,像来自未来
看到这里,我感觉Lisp更像是现代的语言,而不是来自1958年,看看Lisp实现了什么:
- 世界上第一个解释型语言。
- 弱化数据类型,并且完全隐藏底层。
- 提倡函数式编程。
- 支持高级函数用法。(递归、隐式函数)
- all in one思想。
- 等等…
我有些明白了,为什么Lisp称之为“上帝的编程语言”,因为哪怕现在看来也是极为超前的。
代码示例
我编写了一个代码示例,里面用到了Lisp的很多特性和功能,但为了有更好的可读性,括号的格式化仿照了C系风格:
(define (star-line currently target)
(cond ((< currently target)
(display "*")
(star-line (+ currently 1) target)
)(else
(newline)
)
)
)
(define (star currently target)
(cond ((< currently target)
(star-line 0 target)
(star (+ currently 1) target)
)
)
)
(display "你叫什么名字:")
(define name (read-line))
(display (string-append "你好," name))
(newline)
(display "你想要几颗星:")
(define input (read-line))
(define num (string->number input))
(if (and (integer? num) (> num 0))
(star 0 num)
(display "输入的不是有效数字")
)