Y分钟速成Common Lisp

面向记忆的学习材料

快速学习并记住Common Lisp编程语言的基础知识

知识点: Common Lisp的基本语法单元

题目: Common Lisp的两个基本语法单元是什么?

选项:
A. 函数和变量
B. 类和对象
C. 原子和S-表达式
D. 字符串和数字

正确答案: C

解析: Common Lisp的两个基本语法单元是原子(atom)和S-表达式。原子是最基本的数据类型,如数字、符号等。S-表达式是由括号包围的表达式,可以包含原子或其他S-表达式。选项A. B、D虽然都是Common Lisp中的概念,但不是最基本的语法单元。

速记提示: 记住”AS”——Atom和S-expression是Common Lisp的基本语法单元。

知识点: Common Lisp的注释语法

题目: 在Common Lisp中,如何编写一个段落注释?

选项:
A. 使用单个分号(;)
B. 使用两个分号(;;)
C. 使用三个分号(;;;)
D. 使用四个分号(;;;;)

正确答案: C

解析: 在Common Lisp中,注释的规则如下:单个分号(;)用于行末注释、两个分号(;;)用于标准注释、三个分号(;;;)用于段落注释、四个分号(;;;;)用于文件头注释。因此,段落注释应该使用三个分号(;;;)。

速记提示: “三分段”——三个分号用于段落(paragraph)注释。

知识点: Common Lisp的基本数据类型

题目: 在Common Lisp中,表示复数的语法是什么?

选项:
A. (complex 1 2)
B. #C(1 2)
C. 1+2i
D. (1, 2)

正确答案: B

解析: 在Common Lisp中,复数使用#C(real imag)的语法表示,其中real是实部,imag是虚部。因此,正确的表示方法是#C(1 2)。选项A是函数调用形式,不是字面量;选项C是其他语言(如Python)中的表示方法;选项D是常见的坐标对表示法,但不是Common Lisp的复数表示法。

速记提示: 记住”#C”——它像一个”复杂(Complex)”的标志,提醒你这是复数表示法。

知识点: Common Lisp的变量定义

题目: 在Common Lisp中,如何定义一个全局(动态)变量?

选项:
A. (setq var value)
B. (let ((var value)))
C. (defvar var value)
D. (defparameter var value)

正确答案: D

解析: 在Common Lisp中,使用defparameter来定义全局(动态)变量。它的语法是(defparameter var value),其中变量名通常用星号(*)包围,这是一个命名约定。选项A是设置已存在变量的值;选项B是创建局部变量;选项C虽然也可以定义全局变量,但通常用于未初始化的变量。

速记提示: “def-para-meter”——定义参数就是定义全局变量。

知识点: Common Lisp的结构体定义

题目: 在Common Lisp中,如何定义一个名为”dog”的结构体,包含name、breed和age三个字段?

选项:
A. (struct dog (name breed age))
B. (defstruct dog name breed age)
C. (make-struct ‘dog :name :breed :age)
D. (define-structure dog (name breed age))

正确答案: B

解析: 在Common Lisp中,使用defstruct来定义结构体。正确的语法是(defstruct dog name breed age)。这将创建一个名为dog的结构体,具有name、breed和age三个字段。选项A的struct不是Common Lisp的关键字;选项C是创建结构体实例的语法,不是定义结构体;选项D的define-structure不是标准的Common Lisp函数。

速记提示: “DEFinition of STRUCTure”——defstruct就是用来定义结构体的。

知识点: Common Lisp的列表操作

题目: 在Common Lisp中,哪个函数用于将一个元素添加到列表的开头?

选项:
A. append
B. push
C. cons
D. add-to-list

正确答案: B

解析: 在Common Lisp中,cons函数用于将一个元素添加到列表的开头。它创建一个新的cons单元,其car是新元素,cdr是原列表。例如,(cons 1 ‘(2 3))会返回(1 2 3)。append用于连接列表;push是一个宏,会把一个元素加入到原有的列表楷体并返回;add-to-list不是Common Lisp的标准函数。

速记提示: “CONStruct”——cons构造新的列表,把新元素放在最前面;Push——就地修改原有列表。

知识点: Common Lisp的函数定义

题目: 在Common Lisp中,如何定义一个名为”hello”的函数,接受一个名字参数并返回问候语?

选项:
A. (lambda (name) (format nil “Hello, ~a” name))
B. (defun hello (name) (format nil “Hello, ~a” name))
C. (define-function hello (name) (format nil “Hello, ~a” name))
D. (function hello (name) (format nil “Hello, ~a” name))

正确答案: B

解析: 在Common Lisp中,使用defun来定义命名函数。正确的语法是(defun hello (name) (format nil “Hello, ~a” name))。这定义了一个名为hello的函数,接受一个name参数,并返回格式化的问候语。选项A是创建匿名函数(lambda函数);选项C和D不是Common Lisp的标准语法。

速记提示: “DEFine FUNction”——defun用于定义函数。

知识点: Common Lisp的可选参数

题目: 在Common Lisp中,如何在函数定义中指定一个可选参数?

选项:
A. (defun func (required [optional]))
B. (defun func (required optional?))
C. (defun func (required &optional optional))
D. (defun func (required (optional nil)))

正确答案: C

解析: 在Common Lisp中,使用&optional关键字来指定可选参数。正确的语法是(defun func (required &optional optional))。这定义了一个函数,有一个必需参数和一个可选参数。如果调用时不提供可选参数,其默认值为nil。选项A是Python风格;选项B的问号不是Common Lisp的语法;选项D的括号用法不正确。

速记提示: “&”符号在Lisp中经常用于特殊用途,而”optional”显然表示”可选”。

知识点: Common Lisp的相等性判断

题目: 在Common Lisp中,哪个函数用于比较两个数值是否相等?

选项:
A. eq
B. eql
C. equal
D. =

正确答案: D

解析: 在Common Lisp中,=函数用于比较数值是否相等。它可以比较不同类型的数值,如整数和浮点数。例如,(= 3 3.0)返回t。eq用于比较对象身份;eql类似于eq,但也能正确比较字符和数字;equal用于比较序列和一些其他类型的结构相等性。

速记提示: 数学中用”=”表示相等,Common Lisp保持了这个直观的符号。

知识点: Common Lisp的条件语句

题目: 在Common Lisp中,最基本的条件语句是什么?

选项:
A. when
B. cond
C. if
D. case

正确答案: C

解析: 在Common Lisp中,if是最基本的条件语句。它的基本形式是(if test then else)。如果test求值为真,则求值then部分,否则求值else部分。when是if的一个变体,没有else分支;cond用于多重条件判断;case用于基于值的多重分支。

速记提示: 几乎所有编程语言都用”if”作为基本条件语句,Common Lisp也不例外。

知识点: Common Lisp的符号操作

题目: 在Common Lisp中,哪个函数用于从字符串创建符号?

选项:
A. make-symbol
B. intern
C. symbol-name
D. gensym

正确答案: B

解析: 在Common Lisp中,intern函数用于从字符串创建符号。它在当前包中查找或创建一个给定名称的符号。例如,(intern “HELLO”)会返回符号HELLO。make-symbol创建一个新的未引用符号;symbol-name返回符号的名称;gensym生成一个唯一的符号。

速记提示: “intern”在英语中有”扣留”的意思,这里可以理解为”将字符串扣留在符号表中”。

知识点: Common Lisp的包系统

题目: 在Common Lisp中,如何切换到名为”MY-PACKAGE”的包?

选项:
A. (use-package ‘my-package)
B. (in-package :my-package)
C. (switch-to-package ‘my-package)
D. (select-package “MY-PACKAGE”)

正确答案: B

解析: 在Common Lisp中,使用in-package函数来切换当前包。正确的语法是(in-package :my-package)。这会将当前包设置为MY-PACKAGE。注意符号前面的冒号,这是包名称的常用写法。use-package用于导入其他包的符号;switch-to-package和select-package不是标准Common Lisp函数。

速记提示: “in”表示”进入”,就像你实际上”进入”了一个新的包。

知识点: Common Lisp的宏定义

题目: 在Common Lisp中,如何定义一个简单的宏?

选项:
A. (defmacro name (args) body)
B. (defun macro name (args) body)
C. (macro-define name (args) body)
D. (define-macro (name args) body)

正确答案: A

解析: 在Common Lisp中,使用defmacro来定义宏。正确的语法是(defmacro name (args) body)。这定义了一个名为name的宏,接受参数args,主体为body。宏在编译时展开,可以用来扩展语言的语法。选项B是函数定义的语法;选项C和D不是Common Lisp的标准语法。

速记提示: “DEFine MACRO”——defmacro就是用来定义宏的。

知识点: Common Lisp的类型声明

题目: 在Common Lisp中,如何声明一个变量的类型为整数?

选项:
A. (declare (integer x))
B. (the integer x)
C. (type-of x ‘integer)
D. (setf x (make-instance ‘integer))

正确答案: A

解析: 在Common Lisp中,使用declare特殊操作符来进行类型声明。正确的语法是(declare (integer x))。这声明变量x的类型为整数。the用于类型断言,不是声明;type-of返回对象的类型,不是声明;make-instance用于创建类的实例,与类型声明无关。

速记提示: “声明(declare)”变量的类型,就像在正式场合”声明”某事一样。

知识点: Common Lisp的错误处理

题目: 在Common Lisp中,哪个宏用于捕获和处理错误?

选项:
A. catch
B. throw
C. handler-case
D. with-errors

正确答案: C

解析: 在Common Lisp中,handler-case宏用于捕获和处理错误。它允许你指定不同类型的错误条件和相应的处理代码。基本语法是(handler-case expression (error-type (condition) handler-body))。catch和throw用于非局部退出,不是专门用于错误处理;with-errors不是标准Common Lisp的构造。

速记提示: “handler”处理”case”情况,正好对应错误处理的场景。

知识点: Common Lisp的输入输出

题目: 在Common Lisp中,哪个函数用于格式化输出字符串?

选项:
A. printf
B. format
C. print-formatted
D. write-string

正确答案: B

解析: 在Common Lisp中,format函数用于格式化输出字符串。它的基本语法是(format destination control-string &rest args)。destination可以是t(标准输出),nil(返回字符串),或者一个流。control-string包含格式化指令,args是要插入的参数。printf是C语言的函数;print-formatted不是标准函数;write-string只是简单地写出字符串,不进行格式化。

速记提示: “FORMAT”直接表明了这个函数的功能——格式化输出。

知识点: Common Lisp的循环

题目: 在Common Lisp中,哪个是最通用和强大的循环构造?

选项:
A. do
B. loop
C. for
D. while

正确答案: B

解析: 在Common Lisp中,loop宏是最通用和强大的循环构造。它提供了一种类似自然语言的语法来描述复杂的迭代过程。loop可以用于简单的迭代,也可以用于复杂的数据收集和条件迭代。do是一个基本的迭代构造;for通常是loop的一部分;while在Common Lisp中通常通过loop或do来实现。

速记提示: “LOOP”直观地表示了循环的概念,而且它确实是最灵活的循环构造。

知识点: Common Lisp的文件操作

题目: 在Common Lisp中,哪个函数用于打开文件?

选项:
A. fopen
B. open-file
C. open
D. with-open-file

正确答案: C

解析: 在Common Lisp中,open函数用于打开文件。它的基本语法是(open filename &key direction element-type if-exists if-does-not-exist)。这会返回一个流对象,你可以用它来读取或写入文件。fopen是C语言的函数;open-file不是标准函数;with-open-file是一个宏,用于自动处理文件的打开和关闭,但它内部使用的是open。

速记提示: “OPEN”直接表明了这个函数的功能——打开文件。

知识点: Common Lisp的CLOS (Common Lisp Object System)

题目: 在CLOS中,如何定义一个简单的类?

选项:
A. (define-class name (superclasses) slots)
B. (defclass name (superclasses) (slots))
C. (make-class ‘name :superclasses superclasses :slots slots)
D. (class-def name (superclasses) (slots))

正确答案: B

解析: 在CLOS中,使用defclass宏来定义类。正确的语法是(defclass name (superclasses) (slots))。name是类名,superclasses是父类列表(可以为空),slots是槽(属性)定义列表。每个槽可以有various选项,如:initform,:accessor等。选项A. C和D都不是CLOS的标准语法。

速记提示: “DEFine CLASS”——defclass就是用来定义类的。

知识点: Common Lisp的读取宏

题目: 在Common Lisp中,哪个函数用于定义新的读取宏?

选项:
A. def-read-macro
B. set-macro-character
C. define-reader-macro
D. make-dispatch-macro-character

正确答案: B

解析: 在Common Lisp中,set-macro-character函数用于定义新的读取宏。它的基本语法是(set-macro-character char function &optional non-terminating-p)。这会将字符char与函数function关联,使得读取器遇到char时调用function。non-terminating-p参数指定这个宏字符是否是非终止的。选项A和C不是标准函数;选项D用于创建调度宏字符,这是一种更复杂的读取宏。

速记提示: “SET”一个”MACRO CHARACTER”——设置一个宏字符。

知识点: Common Lisp的多值返回

题目: 在Common Lisp中,如何定义一个返回多个值的函数?

选项:
A. (defun func () (return-values 1 2 3))
B. (defun func () (multiple-value-return 1 2 3))
C. (defun func () (values 1 2 3))
D. (defun func () (list 1 2 3))

正确答案: C

解析: 在Common Lisp中,使用values函数来返回多个值。正确的语法是(defun func () (values 1 2 3))。这定义了一个函数func,它返回三个值:1、2和3。调用者可以使用multiple-value-bind或multiple-value-list来接收这些值。return-values和multiple-value-return不是标准函数。选项D会返回一个列表,这与多值返回不同。

速记提示: “VALUES”直接表明了这个函数的功能——返回多个值。

总结

Common Lisp是一种强大而灵活的编程语言,具有以下特点:

  1. 语法简洁:基于S表达式,使用前缀表示法。
  2. 动态类型:变量可以持有任何类型的值。
  3. 交互式开发:支持REPL(读取-求值-打印循环)。
  4. 强大的宏系统:允许开发者扩展语言。
  5. 面向对象编程:通过CLOS(Common Lisp Object System)支持。
  6. 函数式编程:支持高阶函数和闭包。
  7. 条件系统:提供强大的错误处理机制。
  8. 多值返回:函数可以返回多个值。
  9. 包系统:提供命名空间管理。
  10. 丰富的数据类型:包括列表、向量、哈希表等。

掌握这些基础知识点将帮助你开始Common Lisp编程之旅。记住,实践是学习编程语言的最佳方式,所以要多写代码,多使用REPL进行实验。


(defstruct dog name breed age) 在 Common Lisp 中会创建一个名为 dog 的结构体,包含 namebreedage 三个槽(slot,也常被称为字段)。

然而,为了更全面地理解,需要补充一些细节:

  • defstruct 的功能:defstruct 宏不仅仅是创建结构体,它还会自动生成一系列访问器函数(accessor functions),用于读取和设置结构体的槽。 对于上面的例子,defstruct 会自动创建以下函数:
    • make-dog:用于创建新的 dog 结构体实例。
    • dog-name:用于获取 dog 结构体的 name 槽的值。
    • (setf (dog-name dog-instance) new-name):用于设置 dog 结构体的 name 槽的值。
    • dog-breeddog-age:类似地,用于访问和设置 breedage 槽。
    • dog-p:用于检查一个对象是否为 dog 结构体实例。
  • 可选参数:defstruct 接受许多可选参数,允许你自定义结构体的行为,例如:
    • :conc-name:指定访问器函数的前缀。 例如 (:conc-name "my-dog-") 会生成 my-dog-namemy-dog-breed 等函数。
    • :predicate:指定用于检查对象类型的谓词函数的名称。
    • :type:指定结构体的类型。
    • :print-function:指定用于打印结构体的函数。
  • 例子:
(defstruct dog name breed age)

(let ((my-dog (make-dog :name "Buddy" :breed "Golden Retriever" :age 3)))
  (format t "My dog's name is ~a.~%" (dog-name my-dog))
  (format t "My dog is a ~a.~%" (dog-breed my-dog))
  (format t "My dog is ~a years old.~%" (dog-age my-dog)))

;; 输出:
;; My dog's name is Buddy.
;; My dog is a Golden Retriever.
;; My dog is 3 years old.

defstruct 提供了更丰富的功能,允许更灵活地定义和操作结构体。 理解这些可选参数对于编写高效和可维护的 Common Lisp 代码至关重要。


在 Common Lisp 中,special 是一种变量类型,用于声明一个变量是特殊变量。特殊变量与普通的局部变量不同,主要体现在以下几个方面:

特殊变量的特点

  • 动态作用域
  • 特殊变量在它被定义的上下文中具有动态作用域。这意味着,如果在某个函数或代码块中修改了这个变量的值,所有调用这个函数或代码块的地方都能看到这个修改后的值。
  • 使用 declare 声明
  • 使用 (declare (special x)) 可以将变量 x 声明为特殊变量。这样,Lisp 会知道 x 是一个特殊变量,而不是局部变量。
  • 与局部变量比较
  • 普通局部变量在其定义的代码块外是不可见的,而特殊变量在整个动态范围内都是可见的。

示例

以下是使用特殊变量的示例:

(defvar *my-special* 10)  ; 定义一个特殊变量,通常用星号包围命名

(defun modify-special ()
  (declare (special *my-special*))  ; 声明 *my-special* 为特殊变量
  (setf *my-special* (+ *my-special* 5)))  ; 修改特殊变量的值

(modify-special)  ; 调用函数,修改 *my-special*
(print *my-special*)  ; 输出 15

总结

  • 特殊变量在整个动态范围内可见,适用于需要在不同函数之间共享状态的情况。
  • 使用特殊变量时,要小心其作用域,以避免不必要的副作用。

0 0 投票数
Article Rating
订阅评论
提醒
0 评论
最多投票
最新 最旧
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x