变量

elisp 里的变量使用无需像 C 语言那样需要声明。

可以使用 C-h v 查看变量的文档。

set

1
2
(set 'foo "I'm foo")	; => "I'm foo"
(message foo) ; => "I'm foo"

setq

set 命令需要在变量前加上引用。setq 是对 set 的简化。使用它无需在变量前加上引用。

1
2
(setq foo "I'm foo")	; => "I'm foo"
(message foo) ; => "I'm foo"

defvar

defvar 可以声明一个变量。形式:

1
2
(defvar variable-name value
"document string")

它与 setq 不同之处在于:如果变量在声明之前,这个变量已经有一个值的话,用 defvar 声明的变量值不会改变成声明的那个值。另一个区别是 defvar 可以为变量提供文档字符串,当变量是在文件中定义的话,C-h v 后能够给出变量定义的位置。比如:

1
2
3
4
5
6
(defvar foo "Did I have a value?"
“A demo variable") ; => foo
foo ; => foo
(defvar bar "I'm bar"
"A demo variable named \"bar\"") ; => bar
bar ; => "I'm bar"

局部变量

可以用 let 和 let* 进行局部变量的绑定。let 使用的形式是:

1
2
(let (bindings)
body)

bindings 可以是 (var value) 这样对 var 赋初始值的形式。也可以只用 var 声明一个初始值为 nil 的变量。比如:

1
2
3
4
5
6
(defun circle-area (radix)
(let ((pi 3.1415926)
area)
(setq area (* pi radix radix))
(message "直径为 %.2f 的圆面积是 %.2f" radix area)))
(circle-area 3)

C-h v 查看 areapi 应该没有这两个变量。

let 和 let* 的使用形式完全相同,唯一的区别是在 let* 声明中就能使用前面声明的变量,比如:

1
2
3
4
(defun circle-area (radix)
(let* ((pi 3.1415926)
(area (* pi radix radix)))
(message "直径为 %.2f 的圆面积是 %.2f" radix area)))

函数

定义函数

形式:

1
2
3
(defun function-name (argument-list)
"document string"
body)

示例:

1
2
3
(defun hello (name)
"Say hello to user whose name is NAME."
(message "Hello, %s" name))

使用函数

形式:

1
(hello "Emacser")	; => "Hello, Emacser"

每个函数都有一个返回值。这个返回值一般是函数定义里的最后一个表达式的值。

可以使用 C-h f 查看函数的文档。

匿名函数

形式:

1
2
3
(lambda (arguments-list)
"documentation string"
body)

调用方法:

1
2
(funcall (lambda (name)
(message "Hello, %s!" name)) "Emacser")

你也可以把 lambda 表达式赋值给一个变量,然后用 funcall 调用:

1
2
3
(setq foo (lambda (name)
(message "Hello, %s!" name)))
(funcall foo "Emacser") ; => "Hello, Emacser!"

lambda 表达式最常用的是作为参数传递给其它函数

逻辑运算

条件的逻辑运算和其他语言都是很类似的,使用 and、or、not。and 和 or 也同样具有短路性质。很多人喜欢在表达式短时,用 and 代替 when,or 代替 unless。当然这时一般不关心它们的返回值,而是在于表达式其它子句的副作用。比如 or 经常用于设置函数的缺省值,而 and 常用于参数检查:

1
2
3
4
5
6
7
8
9
10
11
(defun hello-world (&optional name)
(or name (setq name "Emacser"))
(message "Hello, %s" name)) ; => hello-world
(hello-world) ; => "Hello, Emacser"
(hello-world "Ye") ; => "Hello, Ye"

(defun square-number-p (n)
(and (>= n 0)
(= (/ n (sqrt n)) (sqrt n))))
(square-number-p -1) ; => nil
(square-number-p 25) ; => t

函数列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(defun NAME ARGLIST [DOCSTRING] BODY...)
(defvar SYMBOL &optional INITVALUE DOCSTRING)
(setq SYM VAL SYM VAL ...)
(let VARLIST BODY...)
(let* VARLIST BODY...)
(lambda ARGS [DOCSTRING] [INTERACTIVE] BODY)
(progn BODY ...)
(if COND THEN ELSE...)
(cond CLAUSES...)
(when COND BODY ...)
(unless COND BODY ...)
(when COND BODY ...)
(or CONDITIONS ...)
(and CONDITIONS ...)
(not OBJECT)

Comments