美文网首页
GNU Emacs Lisp编程入门(学习笔记)

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

作者: yiltoncent | 来源:发表于2015-03-17 18:19 被阅读1757次

    基本概念

    列表

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

    '(rose violet daisy buttercup)
    

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

    原子

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

    • 括号和括号中由空格分割的原子
    • 括号和括号中的其他列表
    • 括号和括号中的其他列表及原子

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

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


    求值

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

    对一个内部列表求值

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

    (+ 2 (+ 3 3))
    

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

    变量

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

    • 函数定义时一组指令,这组指令是由计算机执行的。
    • 一个符号的值可以是LISP中的任意表达式,如一个符号、一个数字、一个列表或者一个字符串。幼稚的一个符号被称为一个变量
    • 一个符号可以同时具有一个函数定义和一个值。

    LISP风格“Hello World"

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

    CL-USER> "hello world"
    "hello world"
    

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

    函数

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

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

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

    CL-USER> (hello-world)
    hello world
    NIL
    

    保存工作结果

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

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

    (defun name varlist &rest body)
    

    在文件中输入以下内容:

    (defun hello-world ()
        (format t "hello world"))
    

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

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

    CL-USER> (hello-world)
    hello world
    NIL
    

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

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

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

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

    • 使用C-x b,在其提示时输入hello.lisp以切换回含有那个文件的缓冲区,然后像之前那样重新编译定义。
    • 加载整个文件。
    CL-USER> (load "hello.lisp")
    T
    

    相关文章

      网友评论

          本文标题:GNU Emacs Lisp编程入门(学习笔记)

          本文链接:https://www.haomeiwen.com/subject/tbiixttx.html