newLISP 初级教程
newLISP — 交互式教程
Hello World!
代码和数据是可以互换的
函数的参数
副作用和 Contexts
表达式序列
可执行文件和动态链接(Executables and Dynamic Linking)
在 OSX, Linux 或其他 UNIX 系统:
在 Windows 系统上目标文件需要 .exe 后缀
绑定(Binding)
List 是一种递归结构
函数(Functions)
高阶函数
lambda 列表
动态范围(Dynamic Scope)
函数参数列表
宏
Contexts
局部作用域(Lexical Scope)
newLISP — 交互式教程
这份文档于 2006 年 5 月被 Rick Hanson (cryptorick@gmail.com) 做了一些修正和更新后被转换成 html 文档。2008 年 12 月被 L.M 更新到 v.10.0 版本. 版权所有 John W. Small 2004。
你可以到 newLISP 官方网站 www.newLISP.org 下载和安装这门语言.
关于这个教程的任何意见和问题请发邮件到 jsmall@atlaol.net 。
中文版翻译时 newLISP 的版本已经到了 10.6 这和当时撰写文档的时候,已经相隔甚远。一些内置函数的名称发生了变化,语言的功能也扩展了很多。我根据实际的情况修改了相应的章节,这样所有的代码就都可以在新的版本上进行测试运行了。
中文翻译:宋志泉(ssqq) QQ: 104359176 电子邮件:perlvim@gmail.com
Hello World!
在你的系统上安装 newLISP 之后, 在 shell 命令行下输入 newlisp
就可以启动 REPL (读取,计算,打印循环).
在 Linux 系统中,你的界面看起来像这样:
1 |
$ newlisp |
2 |
> _ |
如果是在 Windows 平台上,它会是这个样子:
1 |
c:\> newlisp |
2 |
> _ |
在 REPL 启动后,newLISP 会出现一个响应输入的提示:
1 |
> _ |
在下面的提示中输入如下表达式,就可以在屏幕上打印出 “Hello World!“.
1 |
> (println "Hello World!" ) |
newLISP 打印出输入在 REPL 中提示符后的表达式结果,并等待下一次输入.
1 |
> (println "Hello World!" ) |
2 |
Hello World! |
3 |
"Hello World!" |
4 |
> _ |
为什么会打印出两次呢?
函数 println
的执行结果在屏幕上打印出第一行:
1 |
Hello World! |
函数 println
然后返回字符串 “Hello World!“. 这是它最后一个参数,会返回给 REPL, REPL 会把它显示在屏幕上,这是第二行的由来。
1 |
"Hello World!" |
REPL 会计算任何表达式,不单单计算函数.
1 |
> "Hello World!" |
2 |
"Hello World!" |
3 |
> _ |
如果你输入上面的表达式 "Hello World!"
, 它只是返回表达式本身,如果输入数字结果也是一样.
1 |
> 1 |
2 |
1 |
3 |
> _ |
现在你可能会想,成对的括号怎么没用到呢?如果你以前使用主流的计算机语言,像下面的函数调用看起来是不是更自然一点:
1 |
println( "Hello World!" ) |
我相信过段时间你会喜欢下面的写法:
1 |
(println "Hello World!" ) |
而不是:
1 |
println( "Hello World!" ) |
因为一些原因,不能详细解释,等到你看到更多的关于处理列表和符号的 newLISP代码后,也许就会明白。
代码和数据是可以互换的
Lisp 的本意是列表处理(List Processor). Lisp 使用 lists 同时表示代码和数据,它们彼此之间是可以互相转换的。
以前的 println
表达式是一个真正的拥有两个元素的列表。
1 |
(println "Hello World!" ) |
第一个元素是:
1 |
println |
第二个元素是:
1 |
"Hello World!" |
Lisp 总是会将列表作为函数调用进行执行,除非你引用它,从而表明它只是一个字面形式的符号表达式,也就是 – 数据。
1 |
> '(println "Hello World!" ) |
2 |
(println "Hello World!" ) |
3 |
> _ |
一个符号表达式可以再次被当成代码运行,比如:
1 |
> (eval '(println "Hello World!" )) |
2 |
Hello World! |
3 |
"Hello World!" |
4 |
> _ |
Lisp 程序可以在运行时构建数据的字面量,然后执行它们!
1 |
> (eval '(eval ' (println "Hello World!" ))) |
2 |
Hello World! |
3 |
"Hello World!" |
4 |
> _ |
通常单引号 '
是引用 quote
简写形式.
1 |
> (quote (println "Hello World!" )) |
2 |
(println "Hello World!" ) |
3 |
> _ |
你可以想象引用 quote
将它的参数当成字面量返回, 也就是符号化参数.
1 |
> 'x |
2 |
x |
3 |
> (quote x) |
4 |
' x |
5 |
> '( 1 2 three "four" ) |
6 |
( 1 2 three "four" ) |
7 |
> _ |
符号,例如上面的 x
和 three
, 还有符号列表(symbolic lists)在人工智能领域起着举足轻重的角色。这个教程不会探讨人工智能,但是一旦你学会用 Lisp 编程,你将能明白许多人工智能的教科书的 Lisp 的代码含义了。
让我们看看下面的例子:
1 |
> 'Hello |
2 |
Hello |
3 |
> "Hello" |
4 |
"Hello" |
5 |
> _ |
符号 'Hello
和字符串字面量 "Hello"
不同. 现在你就会明白为什么在 REPL 中使用双引号来标注一个字符串,这样是为了和有着相同字母的符号进行区分。
函数的参数
println
函数可以拥有任意个数的参数。
1 |
> (println "Hello" " World!" ) |
2 |
Hello World! |
3 |
" World!" |
4 |
> _ |
上面的代码中,参数一个接一个的合并后,输出到屏幕,最后一个参数的值作为函数的返回值进行返回给 REPL。
通常,参数是从左到右进行计算的,然后将结果传递给函数。传递给函数的参数可以说被完全的计算过了,这就是大家所说的应用序求值(applicative-order evaluation).
但是请注意,函数 quote
并不是这样.
1 |
> (quote (println "Hello World!" )) |
2 |
(println "Hello World!" ) |
3 |
> _ |
如果它的参数是这个:
1 |
(println "Hello World!" ) |
如果它被完全解释后传递,我们将会在屏幕上看到:
1 |
Hello World! |
事实并不是这样,函数 quote
是一种特殊的函数,通常被称为特殊形式函数 “special form”.
你可以在 newLISP 中设计自己的特殊形式函数,这种函数叫做宏(macro), 它的参数能以字面量被调用。这就是正则序求值(normal-order evaluation),我们说这种顺序是惰性的。也就是说,一个宏的参数在传递过程中并不会被直接计算(我们将在下面了解具体情况)。
因此,函数 quote
将参数按字面量传递并返回。在某种意义上,引用 quote
代表了典型的惰性计算原则。它并不对参数做任何运算,只是单单的按照字面量返回它。
如果没有特殊形式函数,其他函数中的流程控制,是不能在只有列表语法的语言中实现的。例如,看看下面的 if
函数.
1 |
> ( if true (println "Hello" ) (println "Goodbye" )) |
2 |
Hello |
3 |
"Hello" |
4 |
> _ |
特殊形式函数 if
接受三个参数:
1 |
语法: ( if condition consequence alternative) |
2 |
3 |
condition(条件) => true |
4 |
consequence(结果) => (println "Hello" ) |
5 |
alternative(替代) => (println "Goodbye" ) |
参数 condition
总是被完全的计算,但参数 consequence
和 alternative
的表达式是惰性的。因为参数 alternative
的表达式可能根本不需要计算.
请注意 if
这个表达式. 它返回的值到底是 consequence
还是 alternative
, 依赖于 condition
是真还是假. 在以上的例子中,alternative
表达式没有后被计算,因为打印到屏幕 “Goodbye” 的副作用永远都不会出现.
如果一个 if
表达式的条件 condition
表达式测试为假,但又没有 alternative
语句,那么它就会返回 nil
. nil
的意思根据不同的环境可能解释为空值(void)或假(false).
注意:在大多数主流计算机语言中,if
只是一个语句,并不会产生返回值。
如果 Lisp 缺乏这个惰性计算特性,它就无法用来实现特殊形式函数或宏(macro)。如果没有惰性计算,大量额外的关键字 and/or 语法就会不得不加入到语言中。
直到现在,��看到几种语法?括号和引用?哦,似乎有点少!
惰性计算带给你的就是,我们自己可以在语言中添加个性化的流程控制方式,来扩展这门语言,订制自己的专用语言。函数和宏的书写将在本教程的后面部分。
更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2014-05/102252p2.htm
newLISP 的详细介绍:请点这里
newLISP 的下载地址:请点这里
为Emacs配置newLISP开发环境 http://www.linuxidc.com/Linux/2013-01/78463.htm
newLISP做GitLab系统备份 http://www.linuxidc.com/Linux/2013-01