elisp学习笔记

参考: http://steve-yegge.blogspot.in/2008/01/emergency-elisp.html

    http://www.gnu.org/software/emacs/emacs-lisp-intro/

 

Lisp中的基本概念

列表List是Lisp的基础,用括号标识其边界。Lisp的名称代表LISt Processing,就是处理列表的语言。因此会在Lisp代码看到层层叠叠的小括号,这种嵌套的括号表达式在Lisp中称为Forms。以下两个例子均为列表

'(this list has (a list inside of it))

(+ 2 3)

 

括号里面没有用括号括起来的,在Lisp中叫原子atoms,它是不可分割的,如字符串(如”this is a text”),数字(如37,511,1729),符号(如‘+’)等,原子之间用空格隔开。

 

列表的运行方法:在emacs中,将光标移到列表(表达式)末尾,敲入C-x C-e. 比如上面的第一个列表执行结果将为(this list has (a list inside of it)),第二个列表执行后输出结果为5。可以看出,如果列表不带单引号,则会将第一个元素当作是函数(’+’在其它语言中可能是操作符,在 Lisp中可以认为是函数),会执行函数相应的指令,否则,会认为第一个元素只是一个普通的符号,执行结果就是列表本身。列表内部的列表也是可以单独执行的,只要把光标放到列表反括号的后面敲入C-x C-e即可,如

(+ 2 (+ 3 3 ))

将光标放到最后一个小括号上面,执行结果为6,放到最后一个小括号后面,执行结果为8。

 

符号除了代表一个函数(如’+’),也可表示一个值,并且这个值还可能是可变的,此时称这个符号为变量。如fill-column表示emacs自动换行的字符数.直接执行下面的变量,执行时echo area会显示70(不同的电脑显示结果不一样)。

fill-column

而如果执行

(fill-column)

则会报错,因为它并不是一个函数。

 

参数是指跟随在函数后面的原子或列表,如(+ 2 3)中的2和3 ,有的函数没有参数,则用空列表表示。参数还可能是字符串或变量的值,参数个数还可以是可变的

(concat “foo” “bar” “baz”)

(substring “foobar” 0 3)  

(+ 2 fill-column)

(+ 3 4 5)

 

显示消息给用户的函数为message,如:

(message "The value of fill-column is %d." fill-column)

 

Lisp的注释由分号开始,直至行尾。

 

Lisp使用set给变量赋值,其使用方法为:

(set 'sum (+ 2 2))

由于set后面加一个飘号的使用频繁非常高,因此用了一个更简便的形式setq来代替:

(setq sum (+ 2 3))  ; setq means "set quoted"

另一个赋值是defvar,它与setq有两个区别。 1. 如果变量没有值时才会给变量赋值,否则保持变量的值不变,也就是说,defvar只用来初始化一个变量。2. defvar多一个参数——会写进文档的描述字符串。

defconst用来定义一个常量,其意义在于暗示此值不应该被修改,尽管可以被修改。如:

(defconst pi 3.14159 "A gross approximation of pi.")

 

let定义局部变量

(let ((variable value)

(variable value)

...)

body...)

例如:

(let ((zebra 'stripes)

(tiger 'fierce))

(message "One kind of animal has %s another is %s."     zebra tiger))

 

布尔值

         符号t表示true

         符号nil表示false

 

算术

C/Java/JS Operator

Emacs Lisp

Example

Result

+

+

(+ 1 2 3 4 5)

15

-

-

(- 6 2 3)

1

*

*

(* 2 -1 4.2)

-8.4

/

/

(/ 10 3)

3 (use floats for float div)

%

%

(% 10 2)

0

<< 

lsh

(lsh 1 5)

32

>> 

ash (negative amount)

(ash -32 -4)

-2

>>> 

lsh (negative amount)

(lsh 32 -4)

2

++

incf (requires 'cl library)

(incf x 6)

x+6

--

decf (ditto)

(decf x 5)

x-5

? : (ternary)

(if test-expr then-expr else-expr)

(if t 3 4)

3

&&

and

(and t t t nil)

nil

||

or

(or nil nil nil t)

t

! (logical-not)

not

(not 3)

nil

~ (bit-not)

lognot

(lognot #b1001)

-10

^ (bit-xor)

logxor

(logxor 5 3)

6

& (bit-and)

logand

(logand 1 3)

1

| (bit-or)

logior

(logior 1 3)

3

(< 5 3)

nil

(> 5 3)

t

<=

<=

(<= 3 3)

t

>=

>=

(>= 5 3)

t

. (field access)

see setf below

n/a

n/a

[] (array access)

aref/aset

(aref [2 4 6] 1)

4

 

如计算数学表达式 (0x15 * (8.2 + (7 << 3))) % 2在lisp中写为:

(% (* #x15 (+ 8.2 (lsh 7 3))) 2)

 

控制流

if/else

(if (>= 3 2)

  (message "hello there"))

if/then/else:

(if (today-is-friday)         ; test-expr
    (message "yay, friday")   ; then-expr
  (message "boo, other day")) ; else-expr

在lisp中,判断函数一般用p结尾。

如果没有else语句而body又有多个表达式,则可用when

(when (> 5 1)

    (message “5 is greater than 1!”)

    (message “5 is greater than 1!!”)

    (message “5 is greater than 1!!!”))

 

循环

while语句的格式为while test body-forms

例子:从1加到10

(setq x 10
      total 0)
(while (plusp x)  ; while x is positive
  (incf total x)  ; add x to total
  (decf x))       ; subtract 1 from x

这里setq给多个变量赋值,后面依次填写参数。

也可使用loop宏,类似其它语言的for语句

(loop with result = '()         ; one-time initialization
      for i downfrom 10         ; count i down from 10
      for j from 0 by 2         ; count j up from 0 by 2
      while (< j 10)            ; stop when j >= 10
      do
      (push (+ i j) result)     ; fast-accumulate i+j
      finally
      return (nreverse result)) ; reverse and return result

 
for..in语句:

    (loop for i in '(1 2 3 4 5 6)
            collect (* i i))           ; yields (1 4 9 16 25 36)

 

Lisp使用catch/throw进行控制流的跳转。

break的实现:

Emacs Lisp

Javascript

(setq x 0 total 0)
(catch 'break
  (while t
    (incf total x)
    (if (> (incf x) 10)
        (throw 'break total))))

var x = total = 0;
while (true) {
  total += x;
  if (x++ > 10) {
    break;
  }
}

 

其中符号'break是可替换成其它值。

continue的实现

Emacs Lisp

Java

(setq x 0 total 0)
(while (< x 100)
  (catch 'continue
    (incf x)
    (if (zerop (% x 5))
        (throw 'continue nil))
    (incf total x)))

var x = total = 0;
while (x < 100) {
  x++;
  if (x % 5 == 0) {
    continue;
  }
  total += x;
}

 

函数

用defun定义函数

语法: (defun function-name arg-list [optional docstring] body)

(defun square (x)
  "Return X squared."
  (* x x))

(square 2)

对于没有参数的函数使用空列表:

(defun hello ()
  "Print the string `hello' to the minibuffer."
  (message "hello!"))

(hello)

 

posted on 2012-08-24 16:45  jianglili  阅读(605)  评论(0编辑  收藏  举报

导航