# Lisp

:一种古老的编译型语言。

  • 虽然古老,但是诞生之后有多次改进,扩展了许多现代编程语言的功能。

# 相关历史

  • 1954 年,IBM 公司的 John Backus 发明了 Fortran 语言。
    • 它是世界上第一种高级编程语言,主要用于公式计算。
  • 1958 年,John McCarthy 发现原始递归函数可以扩展为符号表达式,于是基于 Fortran 发明了 Lisp 语言。
    • 它是世界上第一种支持递归函数的高级编程语言,主要用于人工智能编程。
  • Lisp 语言衍生了多种方言:
    • Scheme :于 1975 年发布。
    • Common Lisp (opens new window) :于 1984 年发布,本文介绍其语法。
    • Racket :于 1995 年发布。
    • Clojure :于 2007 年发布。源代码编译成 Java 字节码之后由 JVM 运行。

# 语法特点

  • 源文件的扩展名为 .lisp 或 .lsp 。
  • 代码可以编译后执行,也可以通过解释器直接执行。
  • 用分号 ; 声明单行注释,用 #||# 声明多行注释。
  • 标识符不区分大小写。
  • 支持定义函数,支持面向对象编程。

# 括号表达式

  • Lisp 程序的主要组成单位:

    • atom :一个数字或标识符。
      • 如果代码中的一个字符串没有用双引号作为定界符,则被当做 atom 。如果它全由数字字符或小数点组成,则视作数字,否则视作变量名、函数名等标识符。如下:
        3.14        ; 数字
        var1        ; 标识符
        Hello       ; 标识符
        "Hello"     ; 字符串
        
      • 特别地,字母 t 表示逻辑真,nil 表示逻辑假或空列表。
    • string :字符串,用双引号作为定界符,支持用反斜杠 \ 转义字符。
    • list :列表,是一个包含任意个 atom 或 list 的括号表达式。
      • 如下:
        (0 1 2 3)
        (0 ( 1 2 ) 3 Hello)
        ( )
        
  • Lisp 的每个语句都放在括号表达式中:

    (write 6)                     ; 调用函数 write 打印一个值,前后要加上括号
    (write-line "Hello World")    ; 打印一个值并换行
    
    • 函数本身不需要括号就可以传入参数,即不需要 ( write(6) )
    • 缺点是括号嵌套多层之后的可读性较差。
  • Lisp 的括号表达式采用前缀表示法:将运算符写在操作数之前。

    (write (+ 1 2 3))             ; 相当于 write(1 + 2 + 3)
    (write (* 3 (+ 1 2) ))        ; 相当于 write((1 + 2) * 3)
    

# 变量

  • 定义全局变量:

    (defvar x 3.14)
    (write x)
    
    • 变量的值只能是数字类型。
  • 定义局部变量:

    (setq x 3.14)
    (setq y x)
    (write y)
    

# 流程控制

  • if 语句:
    (setq x 3.14)
    (if (> x 3)
      (format t "~% x is large enough")       ; if 条件为真时,执行第一个代码块
      (format t "~% x is not big enough")     ; if 条件为假时,执行第二个代码块
    )
    

# 函数

  • 定义函数:

    (defun average (x y)
      (/ ( + x y) 2)
    )
    
    • 函数内最后一个执行的表达式的取值会作为函数的返回值。
  • 调用函数:

    (write(average 10 20))