我正在尝试创建一个将返回一个常量值的函数.
在JavaScript和其他现代命令式语言中,我会使用闭包:
function id(a) {
return function() {return a;};
}
Run Code Online (Sandbox Code Playgroud)
但是Emacs lisp并不支持这些.
我可以创建身份功能和部分功能应用程序的混合,但它也不支持.
那我该怎么做?
如果我做
(add-hook 'haskell-mode-hook
(lambda ()
(setq indent-tabs-mode t)
(setq tab-width 4)
(message "OK")))
Run Code Online (Sandbox Code Playgroud)
在我~/.emacs.d/init.el,然后(lambda ...)当我进入时,它会被执行haskell-mode.
但是,如果我使用这样的函数:
(defun my-add-hook (hook tmode twidth)
(add-hook hook
(lambda ()
(setq indent-tabs-mode tmode)
(setq tab-width twidth)
(message "OK"))))
Run Code Online (Sandbox Code Playgroud)
然后~/.emacs.d/init.el像这样调用它:
(my-add-hook 'haskell-mode-hook t 4)
Run Code Online (Sandbox Code Playgroud)
然后没有任何反应(甚至没有显示"OK"消息).是add-hook一个无法在内部使用的特殊功能defun?我在单独的初始化文件中定义了每个项目设置,该文件检测缓冲区名称并将(lambda ()...)调用添加到相关的主要模式(在上面的示例中haskell-mode); 我想通过使用my-add-hook如上所述的薄包装来减少代码冗长,但我不知道为什么add-hook这么难.
EDIT1:添加了澄清代码.
EDIT2:我尝试使用时收到"文件模式规范错误:( void-variable tmode)"消息my-add-hook.
我试图理解lambdaEmacs Lisp中发现的概念.
在ielm,执行:
((lambda (x) (* x x)) 5)
Run Code Online (Sandbox Code Playgroud)
给了我们25,和
(let ((x 4)) (* x x))
Run Code Online (Sandbox Code Playgroud)
给了我们16.但是,当我这样做时:
(let ((f (lambda (x) (* x x)))) (f 7))
Run Code Online (Sandbox Code Playgroud)
它没有给我49,而是通知我:
*** Eval error *** Symbol's function definition is void: f
Run Code Online (Sandbox Code Playgroud)
不知道为什么,我确定语法是正确的,f是在let?中定义的?
使用cl-flet定义let-ed功能
我们可以真正做到这一点,而无需使用funcall.该cl模块包括Common Lisp的标准功能.我们先导入它:
(require 'cl)
Run Code Online (Sandbox Code Playgroud)
此后我们可以cl-flet用来定义我们的功能:
(cl-flet ((f (x) (* x x)))
(f 7))
Run Code Online (Sandbox Code Playgroud) 我需要创建一个生成如下函数的函数:
(defun add3 (val) (+ 3 val))
Run Code Online (Sandbox Code Playgroud)
应该像这样使用:
(setq adder7 nil)
(fset 'adder7 (make-adder 7))
(adder7 3)
=> 10
Run Code Online (Sandbox Code Playgroud)
理想情况下,函数make-adder应该返回除了参数之外没有任何符号的lambdas,例如:
(make-adder 7)
=> (lambda (val) (+ 7 val))
Run Code Online (Sandbox Code Playgroud)
更新
我尝试过以下天真的实现:
(defun make-adder (n)
(lambda (x) (+ n x)))
Run Code Online (Sandbox Code Playgroud)
但是这会生成一个包含自由符号(不是数字常量!)的lambda,并且它的使用失败.
(defalias 'add1 (make-adder 1))
(add1 2)
=> Debugger error void-variable n
(let ((n 5))
(add1 2))
=> 7
Run Code Online (Sandbox Code Playgroud)
这根本不是我想要的.