[关闭]
@yiltoncent 2015-03-17T10:30:26.000000Z 字数 2163 阅读 3056

GNU Emacs Lisp编程入门(学习笔记1)

Emacs LISP


基本概念

列表

列表由括号括起来,元素由空格分开。

  1. '(rose violet daisy buttercup)

在LISP中,数据和程序都以同样的方式表示。都是由空格分隔的、由括号括起来的单词、数字或者其他列表的列表。列表是LISP的基础

原子

原子是LISP里面不可分割的部分。在一个列表中,原子是由空格意义分割的,原子可以紧接着括号。
LISP的一个列表有三中可能的组成方式:

一个没有任何原子的列表就像这样(),它被称为空列表,可以把它同时看做既是一个原子,也是一个列表

在LISP的日常使用习惯中,“原子”一词不太常用,LISP编程几乎都是关于列表中的符号的。另外,在LISP中,所有用双引号括起来的文本,包括标点符号和空格,都是单个原子。这种原子被称为string。


求值

当LISP解释器处理一个表达式时,这个动作被称为“求值”。我们称,解释器计算表达式的值。

对一个内部列表求值

如果对一个嵌套在另一个列表中的列表求值,对外部列表求值时可以使用受限对内部列表求值所得的结果。这解释了为什么内存列表总是首先被求值的:因为它们的返回值被首先用于外部表达式。

  1. (+ 2 (+ 3 3))

数字8就会显示在回显区。

变量

LISP中,可以降一个值赋给一个符号,就像降一个函数定义赋给一个符号那样。但两者含义不同。

LISP风格“Hello World"

让REPL打印“Hello World”再简单不过。

  1. CL-USER> "hello world"
  2. "hello world"

其工作原理是,因为字符串和数字一样,带有LISP读取器可以理解的字面语法并且是自求值对象;LISP读取双引号里的字符串,求值的时候在内存里简历一个可以对自身求值的字符串对象,然后再以相同的语法打印出来。双引号本身不是在内存中的字符串对象的一部分——它们只是语法,用来告诉读取器读入一个字符串。而打印器之所以在打印字符串时带上它们,则是因为其试图以奕宗读取器可以理解的相同语法来打印对象。

函数

函数是LISP的基本程序构造单元,可以用类似下面的defun表达式来定义:

  1. CL-USER> (defun hello-world () (format t "hello world"))
  2. HELLO-WORLD

defun后面的hello-world是这个函数的名字。像hello-world这种用连字符而不是下划线或是内部大写来形成复合词的方法,是标准的LISP风格
表面上看,这个表达式和你目前见到的所有其他表达式一样,只是另一个被REPL读取、求值和打印的表达式。这里返回值是你所定义的函数名。但是和format表达式一样,这个表达式的副作用比返回值更有用。但与format表达式所不同的是,它的副作用是不可见的:当这个表达式被求值时,一个不带参数且函数体为(format t "hello world")的新函数会被创建出来并被命名为HELLO-WORLD
一旦定义了这个函数,你就可以像这样来调用它:

  1. CL-USER> (hello-world)
  2. hello world
  3. NIL

保存工作结果

在Emacs中可以通过输入C-x C-f来创建一个新文件,然后根据Emacs的提示输入文件的名字。文件存放的位置并不重要。 Common Lisp源文件习惯上带有.lisp扩展名,尽管有些人用.cl来代替。

一旦创建了文件,就可以向其中写入之前在REPL里面输入过的定义。需要注意的是,在输入了开括号和defun以后,在Emacs窗口的底端,slime将会提示它所期待的参数具体形式取决于具体Common Lisp实现,但其形式可能如下所示。

  1. (defun name varlist &rest body)

在文件中输入以下内容:

  1. (defun hello-world ()
  2. (format t "hello world"))

可用集中方式将这个定义输入到LISP环境中,最简单的是当光标位于defun定义内部的任何位置时,输入C-c C-c,这将启动slime-compile-defun命令,将当前定义发给LISP进行求值并编译。

输入C-c C-z切换到REPL中可以尝试调用新函数。

  1. CL-USER> (hello-world)
  2. hello world
  3. NIL

输入C-x C-s可以启动Emacs命令save-buffer

尝试从源文件加载这个函数,着需要退出并重启LISP环境。

执行退出操作可以使用一个slime快捷键:在REPL中输入一个逗号。然后在Emacs窗口底部将提示你输入命令,输入quit,然后按回车。这将退出LISP并且关闭所有slime创建的缓冲区。

现在重启slime,使用M-x slime
这里有几种方式让LISP知道hello-world的定义。

  1. CL-USER> (load "hello.lisp")
  2. T
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注