当前位置: 首页 > 工具软件 > Emacs Lisp > 使用案例 >

水木社区Emacs Lisp简明教程-个人笔记

邹高懿
2023-12-01

我只是把自己原来不清楚的点记录下来,方便自己查阅,同时希望点醒其他人。


defvar和setq

defvar

defvar 可以对变量添加document string(文档说明)
defvar 只用做初始化变量,如果变量之前有值,则不会再进行赋值

(defvar variable-name value
  "document string")

setq

setq 不用像set一样在变量名前加’(单引号)
setq 不仅可以初始化变量,还可以进行变量赋值操作

(setq foo "I'm foo"); => "I'm foo"

let 和 let*

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

(defun circle-area (radix)
 (let* ((pi 3.1415926)
        (area (* pi radix radix)));这里给area赋值用了前面声明的变量pi的值
   (message "直径为 %.2f 的圆面积是 %.2f" radix area)))

let 和 let* 操作的都是局部变量,let块内的局部变量,所以都是在进行初始化操作,之后BODY内执行命令优先处理局部变量
如果我无法说明白,请看下面的演示

(progn
  (setq pi 3.14231241412);全局变量pi=3.14231241412
  (let ((pi 3.1415926);外层let块的局部变量pi=3.1415926
	)
    (setq pi 3);pi(外)被赋值为3
    (message "pi: %.9f" pi);输出结果:3.000000000
    (let ((pi 3.2));内部let块声明局部变量pi=3.2
      (message "%.9f" pi));输出结果为:3.200000000
    (message "%.9f" pi)));处于外层let BODY,输出结果为:3.000000000
(message "pi: %.9f" pi);输出结果为:3.14231241412

if 和 when 和 unless

if

是一个函数,只能带一个执行体,如果要执行多个命令,需要用progn连接他们

when

是一个宏(macro)能够执行多个命令,并且不用progn连接他们
这是他的展开

(macroexp--expand-all '(when (= n 1)
  (message "hello")
  (message "world")
  ))
;(if (= n 1) (progn (message "hello") (message "world")))

unless

是一个宏,看他的展开就会一目了然

(macroexp--expand-all '(unless (= n 1) (message "111") (message "111")))
;(if (= n 1) nil (message "111") (message "111"))

这样就不用加progn也能够实现多条语句执行,因为满足条件执行nil,否则执行其他的所有。


Tips:

Elisp中函数的返回值一般是最后一个表达式的返回值,符号前面如果不加单引号,则会进行求值,所以可以将符号直接放在函数最后当作返回值。如果加上单引号,则是返回符号或者表达式本身。

一个函数后面带p比如,region-active-p,他们一般是用作判断,返回值只有t和nil。


逻辑运算 和 短路运算

有 and or not,他们的返回值不都是是 t 或者 nil 有的是一个值。具体看下面:

and

当所有条件都是non-nil时才为真,但是他返回的可不是t,而是最后一个non-nil值
而如果条件中有一个nil,那么他就立刻返回nil,后面的表达式都不会执行,这是叫做短路

(and 1 2 3 4 5);返回5
(and nil (progn
	   (setq n 10)
	   (message "n=%d" n)));不会执行后面语句,直接返回nil

or

当所有条件都为nil时才返回nil,否则返回他所碰到的第一个non-nil的值

(or nil nil nil nil);返回nil
(or nil nil (progn
	      (message "我被执行了")));执行message命令

not

不具有短路性质,只会返回t 和 nil

小结

  • 逻辑运算:and,or 和 not
  • 短路运算:and 和 or

数据类型

数字

  • 整数
    用most-positive-fixnum 和 most-negative-fixnum两个变量来获取整数范围
    #[2-36][number]来表示一个任意进制的整数
  • 浮点数
    1500.0 15e2 15.0e2 1.5e3 .15e4都是表示一个浮点数
    (/ 0.0 0.0)产生的结果是NaN(Not a Number)

数的比较

= 不是赋值操作符 而是比较操作符
set才被用来进行赋值
并且 = 对于浮点数的相等测试是不可靠的,浮点数是不精确的
(eql)测试数字是否想等,不仅测试数字的值是否想等,还测试数字的类型是否一致
如:

(= 1.0 1);t
(eql 1.o 1);nil 因为浮点数不是整数

/= 是不等于的判断测试
并没有+= -= *=这类操作,只能通过set/setq来实现

数的转换

(float)能把整数转化成浮点数
浮点数转化成整数:

  • truncate(meaning:缩短)转换成靠近0的整数
  • floor 转换成最接近的不必本身大的整数(舍弃小数部分)
  • ceiling 转换成最接近的不必本身小的整数
  • round 四舍五入后的整数,即和他的差绝对值最小的整数

 类似资料: