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 > _

符号,例如上面的 xthree, 还有符号列表(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 总是被完全的计算,但参数 consequencealternative 的表达式是惰性的。因为参数 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