在Emacs Lisp中,“柯里化”一个函数

7
我有许多方便的功能,可以在当前单词或区域上操作,由于懒惰等原因,我将它们构建成了一个模板...
例如,
(defun lower-camelcase-at-point-or-region ()
  "lowerCamelCaseTheCurrent dashed or snake_case word or any words in text selection."
  (interactive)
  (let (pos1 pos2 meat)
    (if (and transient-mark-mode mark-active)
        (setq pos1 (region-beginning)
              pos2 (region-end))
      (setq pos1 (car (bounds-of-thing-at-point 'symbol))
            pos2 (cdr (bounds-of-thing-at-point 'symbol))))
    (setq meat (s-lower-camel-case (buffer-substring-no-properties pos1 pos2)))
    (delete-region pos1 pos2)
    (insert  meat)    
    )
  )

有效地说,除了这一行之外,这都是标准模板内容。
(setq meat (s-lower-camel-case (buffer-substring-no-properties pos1 pos2)))

在缓冲区子字符串上调用s-lower-camel-case的位置。我想重复使用点或区域的东西,但不是到处复制它(因为那很愚蠢,而且难以维护)。

所以我真正想知道的是,我能否在Emacs Lisp中进行函数柯里化?

当我尝试这样做时...

(defun do-stuff-on-point-or-region ()
  "Do stuff."
  (interactive)
  (operate-on-point-or-region 's-lower-camel-case)
)

定义 operate-on-point-or-region 为...:
(defun operate-on-point-or-region (fn)
  "Pick the substring at point, or region 
   and replace it with the output of fn"
  (let (pos1 pos2 meat)
    (if (and transient-mark-mode mark-active)
        (setq pos1 (region-beginning)
              pos2 (region-end))
      (setq pos1 (car (bounds-of-thing-at-point 'symbol))
            pos2 (cdr (bounds-of-thing-at-point 'symbol))))
    (setq meat (fn (buffer-substring-no-properties pos1 pos2)))
    (delete-region pos1 pos2)
    (insert  meat)    
    )
)

我得到的错误信息是:Symbol's function definition is void: fn。
我是不是傻傻地以为在Emacs Lisp中可以进行柯里化?还是我做错了什么?
2个回答

8

我想补充一点,在Emacs lisp中不能进行柯里化 -- 函数应用不是柯里化,因为它不遵循柯里化的公式。

柯里化是指将函数应用于部分参数并返回另一个函数。由于动态作用域的原因,在Elisp中无法实现这一点。

编辑:更新

现在Emacs GNU拥有闭包。


我认为我尝试做的是柯里化,这样想错了吗? - ocodo
事实证明,我认为我想做的更好被称为组合,因为我没有提供函数参数(正确的柯里化),只是在另一个函数的主体中提供要调用的函数作为别名。 - ocodo
1
自从24.1版本以来,Emacs原生支持词法作用域(因此也支持闭包)。 - Stefan
1
考虑更改帖子的标题,也许改为关于高阶函数或使用函数值参数的内容。关于澄清柯里化的讨论可能仍然有助于一些人,但对于那些正在搜索的人来说,标题可能会误导。 - Drew
请随意更改,以您认为更好的方式进行修改,但请不要篡改名称,否则我将撤销更改。 - alinsoar
显示剩余5条评论

5
首先,Emacs Lisp 在某种程度上是 2-Lisp,因此以下内容是无效的:
(defun foo (fn)
  (fn 3)) ;; DOES NOT WORK!

相反,你需要执行以下操作:
(defun foo (fn)
  (funcall fn 3))

如果你将(setq meat (fn替换为(setq meat (funcall fn,那么代码应该可以正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接