使用 Emacs 大概也有大半年了,越用越觉得它的强大,始终都有惊喜,每次看到一个功能,心中想:Emacs 可以吗?答案真的往往会是 Yes!
(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
上面这种充满括号的奇怪的语言叫 Lisp,它是仅次于 Fortran 的最老的高级程序设计语言,名称来源于 LISt Processing,它有两个方言,分别是 Common Lisp 和 Scheme。 Emacs lisp (elisp) 来源于 Common Lisp。使用 Emacs,如果不能自己打造适合自己的功能,虽然仍然可以享受 Emacs 带来的流畅和便利,但却会与另一种乐趣失之交臂,这篇文章简要叙述 elisp 的基本概念和语法。
Hello World
(message "Hello, World!")
使用 C-x C-e 执行,便可以从 minibuffer 中看到这段代码的输出,简单吧?
变量
(set 'numstr 'nine)
(setq numstr 'nine)
set 和 setq 用来对变量赋值,变量不需要事先声明,而且都是全局的。
在 C 中,int x = 3; 表示将 3 赋值给 x,我们不能直接再使用 x 这个 symbol,因为它已经代表了整型 3 或者代表之后重新赋的新值,如果需要使用 x,那就只能重新定义 char c = ‘x’,而在 elisp 中,我们针对的就是 symbol,也就是说可以同时使用 x 和 x 所代表的值。比如上面代码,set 语句中 number 和 nine 前面都有一个 ' (quote) 符号,这个符号到底做什么用呢?
它告诉 Lisp 解释器不要去执行这个 symbol,而是直接使用。比如在 L1 执行完后,numstr 代表的是 nine,而 'numstr 仍然指的是 numstr. 为了书写方便,setq 免去了 ',作用同 set。
(let ((name 'Chris)
(age '26))
(message "Name is %s, %d years old" name age))
let 用来定义在特定区域中的局部变量,还有两一种形式,如下
(let (name age)
(setq name 'Chris)
(setq age '26)
(message "Name is %s, %d years old" name age))
运算
(+ 1 2) ; = 3
(+ 1 2 3) ; = 6
(- 8 5) ; = 3
(* 2 3) ; = 6
(/ 7 2) ; = 3
(/ 7 2.0) ; = 3.5
(% 9 4) ; = 1
(expt 2 3) ; = 8
这里需要强调的是如果需要输入浮点数时,需要在数字后面加 .0,否则还是会被当整型处理的。如 L5 & L6。
比较
在 elisp 中,false 用 nil 来表示,空列表也用 nil 来表示,其余的都是 true,也就是说 0 和 空字符串也是 true。
(< 2 3) ; = t
(> 2 3) ; = nil
(<= 2 2) ; = t
(>= 2 3) ; = nil
(= 2 3) ; = nil
(string= "he" "he") ; = t
(string< "he" "ie") ; = t
(not (< 3 2)) ; = t
(or (< 3 2) (< 2 3)) ; = t
(and (< 3 2) (< 2 3)) ; = nil
string< 比较的是字符串的字典顺序,没有 string>。
表达式
(if (< 3 2)
(message "3 < 2")
(message "3 > 2"))
(when (< 2 3)
(setq x 2)
(setq y 3)
(message "%d < %d" x y))
(setq x 0)
(while (< x 4)
(print "hit ")
(setq x (1+ x)))
(progn
(setq x 2)
(setq y 3)
(setq z (+ x y)))
条件判断 if,t 则执行下一句 L2,nil 则执行第三句 L3,when 表示如符合条件,就执行所有语句,while 为循环语句,L10 打印出 4 个 hit,progn 表示一个代码块,返回最后一个语句的返回值。
(setq x 9)
(cond
((<= x 0) 0)
((= x 1) 1)
((> x 1)
(+ x 1)))
cond 用来列出一系列条件,以及满足该条件时的动作,上面代码表示当 x<=0 时,返回 0,当 x=1 时返回 1,当 x>1 时,返回 x+1 的值。
函数
(defun show (type)
(message "This is a my first %s function" type))
(show 'demo)
如果想要在 Emacs 中使用 M-x 调用的话,需要加 (interactive)
(defun yeah ()
(interactive)
(message "yeah!"))
interactive 可以带很多参数,具体请参考。
lambda 用来定义匿名函数
((lambda (number) (* 7 number)) 3)
在函数定义后加参数就可以调用该匿名函数了。