add-hook和lambda ?

#'function 不是返回函数名,是返回函数名所指代的函数对象

2 个赞

这个描述不太合理, add-hook 说白了,就是添加一个函数对象,

正儿八经的用法只有两种:

  1. (add-hook 'xxx #'function)
  2. (add-hook 'xxx (lambda () (fsfsdf)))

这个更准确的说: 是一个函数调用的表达式, 不是函数

其实我对其也是一知半解,如果 #'function 返回的是函数所指代的对象,那么

(defun a () "return a")
(setq b #'a)

(b)  <-  这里却调用出错 Symbol’s function definition is void: b

因为 elisp 是 lisp-2, 就是说, 一个符号既可以表示变量,又可以表示函数

表示变量的时候, 从变量字典里面查询, 表示函数的时候,从函数字典里面查询

(setq b #'a) 是将变量字典里面的 b 设置为 a 对应的函数对象 但执行 (b) 的时候, 是需要从 函数字典里面 找 b 对应的东西,显然没有

1 个赞

因为 symbol 同时有 value slot 和 function slot,设置后者你需要 fset。

1 个赞

Elisp 和 Scheme 不太一样,Scheme 的语法是彻底统一的,所有的语法元素都是 S-expression,define,let 都是 lambda 的语法糖。Elisp 里是区分 函数 和 匿名函数的

(defun hello1 ()
  (message "hello"))

(hello1)
;; 也可以 (funcall 'hello1),这也是 add-hook 的函数要 quote 的原因,
;; (如果和Scheme一样是应用序求值,会先对表达式求值,所以如果是 (funcall hello1) ,hello1会先被求值,而 hello1没有返回值,所以会有 void 错误)
;; 可能底层 run-hook 使用的是 funcall 的机制,而 add-hook 里 直接写 lambda 表达式没这个问题

;; Elisp对lambda求值的方式是funcall,(funcall (lambda () (message "hello"))) 
;; 这就是 Elisp 比 Scheme 蹩脚的地方,Scheme 的求值都是通过括号作用域,是一致的
;; Elisp:   (funcall (lambda (x) (message "hello %s" x)) "Jack")
;; Scheme:  ((lambda (x) (message "hello %s" x)) "Jack")
(setq hello2 (lambda () (message "hello")))
(funcall hello2)
;; (hello2) error
1 个赞

(funcall b) 就可以, 首先执行 b 的时候,将其作为变量,随意返回值是 变量字典里面的 那个函数对象, funcall 调用这个函数对象,就得到需要的了

你要 (funcall b) or (fest 'b #'a)

这个说法不太恰当

原来如此,这样就能解释function与普通值之间的区别了,但是为什么这样做呢?

为了让 宏 编写起来更容易,

1 个赞

其實只是添加了个 Object 到 xxx-hook 里。加的時候隨便加啥都行。就是 run-hook 的時候出錯。

从以前的文献来看, scheme 选择 lisp-1 是为了让 lisp 更简单,更加适用于递归, 但 lisp-1 相应的也增加了编写宏的难度, common lisp 选择 lisp-2, 虽然让语法稍显丑陋,但降低了宏编写的难度, 只是抉择的侧重,没有对错之分

2 个赞
(define fun-123 () (print 1))
(setq x "123")
(funcall (intern (concat "fun-" x)))
;; => 1

Scheme 要做这个一定要 eval,但 funcall 效率 是 eval 的几十倍。

这是黑科技, 除非是必须这么搞,否则不要搞这种东西, 容易自残

Real Man doesn’t afraid use of BLACK TECH(e.g. goto).

After all, Lisp is the biggest BLACK TECH.

这个本来就不是函数名: ((lambda () (message “ffff”)))

当eval 上面表达式的时候, 从左到右执行上面表达式的各个子表达式,首先遇到的是lambda表达式,这个表达式执行的结果是它本身对应的函数,执行完后,最后执行总体表达式,就是调用这个函数

而且 add-hook 也不建议使用 lambda

原来如此 :sweat_smile: