欢迎来到Lisp

0. Lisp系统的交互式前端(REPL)


刚接触Lisp,会发现每种Lisp的实现都会带有REPL(read - eval - print -loop)。
这里记录一下REPL相关的说明及问题。

  • 顶层(toplevel)
    在任何lisp系统中的交互式前端(repl),叫做顶层

  • 中断循环(break loop)
    如果输入了一些Lisp无法理解的东西,它会打印出一个错误信息,然后进入一个叫做
    中断循环的顶层。
    中断循环给予有经验的程序员一个找出错误原因的大集会,不过对于初学者可能只能
    跳出这个循环了。
    每个Lisp实现的REPL的中断循环跳出的方式不通,请根据提示使用。

1. 形式(Form)


Lisp中使用S表达式进行程序的书写。通过左括号( 表示表达式开始,右括号 )表示表达式结束。
正式因为使用了这种表达式,所以Lisp的语法十分简单,因为除了像1这种原子外,都是括号中的表达式。

2. 求值(Evaluation)


Lisp使用前缀表达式,类似(+ 1 2)这种形式。括号内的第一个元素是函数,后面的就是函数的参数。

Lisp中使用quote作为一种保护表达式不被求值的方式,quote也可以缩写为'

3. 数据(Data)


Lisp提供了在其他预言中找的到的及找不到的数据类型。如,整数(integer)、字符串(string)等其他语言中可以找到的数据类型。还有如,符号(symbol)与列表(lists)等,在其他语言中找不到的数据类型。

  • 符号(通常) 不对自己身求值,所以需要使用quote引用它。

  • 列表是由被括号包裹住的零个或多个元素来表示的。括号内的元素可以是任何类型。
    使用列表不许要引用(quote或者其缩写'),不然Lisp会以为是一个函数调用。

  • list函数可以用来创建列表。但不同的是,由于list是函数,所以它的实参自然会被求值。

4. 列表操作(List Operations)


  • cons函数用来构造列表

  • car函数获取列表的第一个元素

  • cdr函数获取列表除第一个元素外的所有元素

  • third函数可以获取列表的第三个函数,通过的还有first、second等等。

5. 真与假(Truth)


在Common Lisp中,t表示逻辑真nil表示逻辑假
将返回值逻辑真逻辑假的函数称为谓词(predicate)。所以谓词的名字通常以p结尾。

  • listp函数判断是否为列表。
  • null函数判断是否为空(假)。
  • not函数对参数进行逻辑非判断。
  • if条件,通常接受三个表达式,一个test表达式,一个then表达式和一个else表达式。若test为逻辑真则对then表达式求值,并返回表达式的值。
    否则,对else表达式求值,并返回表达式的值。
    if的else实参是选择性的,如果不写,默认是nil。
  • and宏对任意参数进行逻辑与判断。
  • or宏对任意实参进行逻辑或判断

6. 函数(Functions)


使用defun定义新函数,Lisp不对程序(program)过程(procedure)函数(function)做区别。

7. 递归(Recursion)


函数自己调用自己称为递归

  • eql函数(谓词)测试两个实参是否相等
  • member测试第一个实参(元素)是否为第二个实参(列表)中的成员。

8.阅读Lisp(Reading Lisp)


使用缩进来阅读及编写程序,不要只盯着括号看。任何好的编辑器都会又括号匹配的功能。

9. 输入输出(Input and Output)


  • format格式化输出
  • read标准输入函数

10. 变量(Variables)


  • let可以创建新的局部变量,在特定的上下文中使用。
    let表达式有两个部分
    第一部分为一组创建新变量的指令,形式为(variable expression)。
    第二部分为一个有表达式的函数体,在函数体内最后一个表达式的求值结果为let的返回值。

  • numberp(谓词)用来测试实参是否为一个数字

  • defparameter用来创建一个全局变量,全局变量的命名通常以开始,并以结束。

  • defconstant用来创建全局常量。不需要给全局常量一个独一无二的名字,因为如果相同名字存在,会产生重复定义的错误。

  • boundp函数用来检查实参是否为全局变量全局常量

11. 赋值(Assignment)


  • setf是赋值操作符,可以给全局或局部变量赋值。
    setf的第一个实参可以是表达式变量名
    如果setf的第一个实参是符号(symbol),并且不是某个局部变量的名字,则setf会把这个符号设为全局变量。也就是隐式的创建全局变量。
    但是还是推荐使用defparamter明确地创建全局变量。

12.函数式编程(Functional Programming)


函数式编程意味着撰写利用返回值工作的程序,而不是修改程序中的某些东西。换言之,只使用函数的返回值,而不使用函数的副作用。

函数式编程允许使用交互式测试(interactive testing)

13.迭代(Iteration)


当想要重复做一些事情的时候,迭代比递归来的更自然。

  • do宏是Common Lisp中最基本的迭代操作符。

    • 第一个实参是一组变量说明列表,(variable initial update)。
      其中variable是符号,initial与update是表达式。变量会被赋予initial表达式的值 作为初始值。每一次迭代,都会被赋予update表达式的值。
    • 第二个实参包含一个货多个表达式。其中,第一个表达式用来测试迭代是否结束。
      而之后的表达式则被依次求值,直到迭代结束。其中最后一个值会被当作do的返回值返回。
    • 其余的实参则组成了循环的函数体。每次迭代,都会被依序求值。
  • progn接受任意数量的表达式,依序求值,并返回最后一个表达式的值。

  • dolist接受该形式的实参(variable expression),并在后边跟着一个具有表达式的函数主体。函数主体会被求值,而变量相继与表达式所返回的列表元素绑定。

14. 函数作为对象(Functions as Objects)


Lisp中,函数与符号、字符串一样是第一类对象。

  • function特殊操作符返回接受实参关联的对象,缩写为#',称为升引号(sharp-quote)。
    升引号后接函数名便可以将函数当作实参传给函数,function +#'+

  • apply接受一个函数和一个实参列表,并返回把传入函数应用到实参列表的结果。
    apply接受任意数量的实参,最后一个是列表即可。

  • funcall与apply的效果相同,只是不需要把实参包装成列表。

  • lambda创建匿名函数使用 (funcall #'(lambda (x) (+ x 100)) 1)

15. 类型(Types)


在Common Lisp中,数值才是又类型的,而变量没有。
类型又fixnumintegerrationalreal、numberatomt
其中t是所有类型的基类(supertype)

  • typep函数接收一个对象和一个类型,然后判断对象是否为该类型

习题(Exercises)


  • (a) 14
  • (b) '(1 5)
  • (c)7
  • (d)'(nil 3)
  • (cons 'a '(b c))
  • (cons 'a (cons 'b '(c)))
  • (cons 'a (cons 'b (cons 'c ())))
(defun our-get-fourth (lst)
        (car (cdr (cdr (cdr lst)))))
(defun our-max (first-num second-num)
      (if (> first-num second-num)
        first-num second-num))
  • (a)遍历x,遍历完毕后,返回一个nil
  • (b)在y中查找x,如果找到,则返回元素在列表中的位置,如果没有找到则返回nil。
  • (a)x为car就可以得到相同的结果
  • (b)x为or可以得到相同的结果
  • (c)x为apply可以得到相同的结果
  (defun our-list-element (lst)
    (if (null (car lst))
      nil
      (if (listp (car lst))
        t
        (our-list-element (cdr lst)))))
  • (a)
    • 递归版本
      (defun print-point-rec (num)
        (if (zerop num)
          'done
          (progn
            (format t "~A" ".")
            (print-point-rec (- num 1)))))
      
    • 迭代版本
      (defun print-point-ite (num)
        (do ((i num (- i 1)))
          ((zerop i) 'done)
          (format t "~A" ".")))
      
      
  • (b)
    • 递归版本
      (defun count-list-rec (lst)
        (if (null lst)
           0
          (+ 1
             (count-list (cdr lst)))))
      
    • 迭代版本
      (defun count-list-ite (lst)
        (let ((len 0))
          (dolist (obj lst)
            (setf len (+ 1 len)))
            len))
      
  • (a)该函数接受一个数字列表是没问题,但是如果接受的是空列表或字符列表,则会报错。

  • (b)该函数没有结束条件,不论传入何种列表都会死循环。

  • 更改后为

    (defun summit-second (lst)
       (let ((x (car lst)))
         (if (null x)
         0
         (if (numberp x)
           (+ x (summit-second (cdr lst)))
           (summit-second (cdr lst))))))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容