我并沒有看到具体哪本 Common Lisp 有讲 eval
实現的。
不是 eval 实现, 是 lisp 执行规则。。。。
回过头來,我并未发現 (funcall (function ...))
的定义有何不妥。
First get form’s function def, then call the function.
我有时候会懒惰写成这样
(define-key evil-motion-state-map (kbd "C-j")
(defun my-xref/find-definitions ()
(interactive)
(if lsp-mode (lsp-ui-peek-find-definitions) (spacemacs/jump-to-definition))))
调用lsp-mode
的xref-find-definition
弹出来的:
Visit tags table(default TAGS): my-dir
这是要配置什么东西么,我看lsp-mode
的demo 的时候,都是直接跳转的。最近想用 lsp-mode
, 想了解这个
我越看越看不明白了……
楼主啊,你前两天还在知乎上赞了这篇用java写一个lisp解释器,里面有Paul Graham的roots of lisp的中译版,里面讲了如何自举lisp,包括怎么在已有lambda时定义出defun(文章里叫label,他讲的大概是上面大家说的lisp-2)。你如果看了的话,这个帖子的问题应该不难理解(虽然讨论里带到的东西我还有不少疑惑吧)
defun
的文档说The return value is undefined.
?
这个帖子已经爆炸了,无关内容快去另开帖
哎……我的lisp水平就是三脚猫而已……
而且我始终有点拿其他语言往上套的思想,所以就提了这么个愚蠢的问题……
和 Root of Lisp 沒关系。那是最早期的 Lisp,Emacs Lisp 的设计己经变了很多。label 更是早就废弃了。另外 Root of Lisp 里面实現的是 Lisp-1.
然而大多數時候都能起作用。
FWIW,关于 defun
的返回值的变化,Emacs 24.3 的 NEWS 有提及:
我不觉得,用已经有的知识去理解未知的信息是人学习的基本方式,产生混乱是明白的开端,你这个帖子开的好,比那种字体对齐,org导出中文pdf之类的月经贴要有意思的多,也有价值的多
不建议这么写,看起来很怪异。。。。
另外,let over lambda 宏之前的章节建议看一看。。。
还有onlisp宏之前的章节
On Lisp 的精隨其實在后面的 Continuation.
你一下回复这么多,论坛没有提示你
如果要一次回复多个人,试试在一次回复中不断引用他们的回复
么
楼上诸位展开太深了。
如果只是回答:
很简单,一个字:懒
懒惰的写法:
(add-hook 'xxx-mode-hook
(lambda ()
...))
不厌其烦的写法:
(defun foo (lambda ()
...))
(add-hook 'xxx-mode-hook 'foo)
楼主后面又问了,为什么 add-hook
第二参数必须是 FUNCTION,不能是 S 表达式。答案也很简单:因为 add 之后,将由 (funcall FUNCTION)
来执行传进来的函数,如果不是函数就会出错。而参数列表本身不具备约束力,传什么都可以。
接下来就是函数名的问题了。函数执行之前,首先要对其参数进行求值,所以如果直接写:
(add-hook 'xxx-mode-hook foo)
那么 foo
就会被当作变量处理了,可以通过 M-x ielm
来观察这一求值过程:
ELISP> (defun foo () (message "foo"))
foo
ELISP> foo
*** Eval error *** Symbol’s value as variable is void: foo
ELISP> 'foo
foo
ELISP> (defvar bar "bar")
bar
ELISP> bar
"bar"
ELISP> 'bar
bar
所以写成 'foo
确保传进去的是 SYMBOL:
(add-hook 'xxx-mode-hook 'foo)
;; 等效
;; (add-hook (quote xxx-mode-hook) (quote foo))
虽然传递函数名和 lambda 执行效果没什么区别,但还是有些需要注意的,例如:
(add-hook 'xxx-mode-hook 'foo)
之后,xxx-mode-hook
的内容是
(foo ;; <-- 最近添加
bar
quux
...)
而 (add-hook 'xxx-mode-hook (lambda () (message "foo")))
之后,其内容则是
((lambda () (message "foo")) ;; <-- 最近添加
bar
quux
...)
所以如果是传递的是函数名,将来需要改变函数 foo 的行为,直接修改就可以了。但如果传递的是 (lambda ...)
,要修改就比较麻烦了,必须整个 (lambda ..)
一字不漏抄一遍:
(remove-hook 'xxx-mode-hook (lambda () (message "foo")))
然后,修改,重新添加:
(add-hook 'xxx-mode-hook (lambda () (message "bar")))
所以说,偷懒是有代价的。
(defun ...)
和 (lambda ...)
的关系,对应到 c 语言,我感觉因类似指针和结构体的关系(毕竟 c 不能把函数当值传递):
(add-hook 'xxx-mode-hook 'foo) ;; 指针(传引用)
(add-hook 'xxx-mode-hook (lambda ()...)) ;; 结构体(传值,一大拖东西)
实际上,(defun ...)
展开之后也是个 lambda,只不过有了一个别名,例如 foo:
(defun foo ()
(message "foo"))
;; 展开 =>
(defalias (quote foo)
(function
(lambda nil (message "foo"))))