Emacs Lisp
Haskell 倾向于组合(compose)函数来完成一个综合功能
Lisp 倾向于用一个函数完成它自身的目标, 且提供各种参数开关用于改变该函数的功能
Lisp 倾向于用一个函数完成它自身的目标, 且提供各种参数开关用于改变该函数的功能
M-x lisp-interaction-mode
进入Lisp交互模式(一些主模式本身就已经具备此模式)C-j
计算光标位置之前的表达式, 在下一行输出结果C-x C-e
计算光标位置之前的表达式(通常光标位置应为最后一个后括号), 在Emacs底部的minibuffer区输出结果以上两种方法都只能运行一条表达式, 而非整个文件里的表达式.
通常的Emacs Lisp代码编写流程:
- 1.编写一个函数
- 2.通过
C-x C-e
安装此函数 - 3.测试和改进此函数的功能
- 4.循环1-3
(+ 1 2)
加法运算(Lisp使用前缀运算符); 赋值字符串John Wick到变量user-name(set 'user-name "John Wick"); 极少使用(setq user-name "John Wick"); 最常用, 与set的区别在于无需输入符号(symbol)前的单引号; 同时赋值多个变量(setq variable1 t; True variable2 nil; False variable3 '("A" "list" "of" "things")')
; 定义(defun func () (message "Hello, %s" name))(defun multiply-by-seven (number) "Multiply NUMBER by seven." (* 7 number)); 执行(func "BlackGlory")
(defun hello () (insert "Hello, I am " my-name))
将上述内容定义为一个名为hello的函数(hello)
调用hello函数(defun hello (name) (insert "Hello " name))
有名为name的参数的hello函数(hello "BlackGlory")
调用有参数的hello函数用
progn
函数创建连续的多条表达式:(progn (switch-to-buffer-other-window "*test*") (erase-buffer) (hello "you") (other-window 1))
用
("绑定到局部变量"的意思等同于"创建局部变量", 只是术语不同罢了),
接下来在调用hello函数时传入此local-name变量
(
let
函数将值"you"绑定到局部变量local-name上("绑定到局部变量"的意思等同于"创建局部变量", 只是术语不同罢了),
接下来在调用hello函数时传入此local-name变量
(
let
也可以创建连续的多条表达式, 此处就不用 progn
了, 显然之后的参数全部都是此local-name变量的作用域范围):(let ((local-name "you")) (switch-to-buffer-other-window "*test*") (erase-buffer) (hello local-name) (other-window 1)); 绑定多个变量(let ((zebra 'stripes) (tiger 'fierce)) (message "One kind of animal has %s and another is %s." zebra tiger)); 变量的默认值为nil(let ((birch 3) pine fir (oak 'some)) (message "Here are %d variables with %s, %s, and %s value." birch pine fir oak)); Here are 3 variables with nil, nil, and some value."
(format "Hello %s!\n" "visitor")
格式化字符串混合了函数参数和局部变量:
(defun greeting (name) (let ((user-name "John Wick")) (insert (format "Hello %s!\nI am %s." name your-name))))
(read-from-minibuffer "Enter your name: ")
从minibuffer读取用户输入(if (> 5 4) (message "5 is greater than 4!"); then-part (message "5 is not greater than 4!")); else-part(> 5 4); 返回 t, 意为真值
'(this list includes "text between quotation marks."); 创建一个值为列表的变量(如果不在列表前加上'则Sarah会被认为是一个函数)(setq list-of-names '("Sarah" "Chole" "Mathilde")); 构造一个在原列表头部加入新元素的新列表(cons 'buttercup ()); (buttercup)(cons 'daisy '(buttercup)); (daisy buttercup); 获取列表长度(length '(buttercup)); 1; 获取列表的第一个值(相当于Haskell的head)(car list-of-names) ; 获取列表第一个值以外的值(相当于Haskell的tail)(cdr list-of-names) ; cdr的重复x次版本(nthcdr 2 '(pine fir oak maple)); (oak maple); 原地设置列表项的值(setq animals '(giraffe antelope tiger lion))(setcar animals 'hippopotamus); (hippopotamus antelope tiger lion)(setq domesticated-animals '(horse cow sheep goat))(setcdr domesticated-animals '(cat dog)); (horse cat dog); 把一个值加到列表的开头(函数式语言里列表数据结构的push方向和命令式语言相反), push是少数直接对列表操作的函数, 不遵守函数式的不可变范式(push "Stephanie" list-of-names); 为list-of-names的每一个值调用hello函数(返回mapped之后的列表)(如果不在hello函数前加上'则会被当作是一个名为hello的变量然后出错)(mapcar 'hello list-of-names)
(while x y); 以x的值为nil时退出循环, 其他值执行循环体y; 对列表循环(while list (print (car list)) (setq list (cdr list))); 重新给list赋值; 计数器循环(while (< count desired-number) ; body... (setq count (1+ count))); count自增
当查找到"Hello"时将其替换为"Bonjour":
(while (search-forward "Hello") (replace-match "Bonjour"))
(buffer-name); 文件名(buffer-file-name); 完整路径名
(point); 返回当前光标位置(buffer-size); 返回整个文件的缓冲区大小(字符数量)
(insert "Hello World")
在光标处插入字符串Hello World(insert "Hello" " World")
与上一行一样, 但传了两个参数(insert "Hello, I am " my-name)
在光标处插入字符串"Hello "和变量my-name的值绑定F1到函数func:
(global-set-key (kbd "<f1>") 'func)
C-h i m elisp
查看官方手册C-h f <函数名>
查询函数文档C-h v <变量名>
查询变量文档