• 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)

  • 相关阅读:
    jquery height
    正则表达式的一点奇怪
    this和call
    ajax views
    史上变态的模块
    在php中有什么用
    localhost访问不了
    $.extend abc
    $.extend
    和人沟通的一个要点
  • 原文地址:https://www.cnblogs.com/jiangli/p/elisp_note.html
Copyright © 2020-2023  润新知