emacs - Elisp:在 Let 中绑定(bind)一个 lambda 并执行它

标签 emacs lisp elisp

<分区>

我试图理解 Emacs Lisp 中的 lambda 概念。

ielm 中,执行:

((lambda (x) (* x x)) 5)

给我们 25

(let ((x 4)) (* x x))

给我们 16。但是当我这样做时:

(let ((f (lambda (x) (* x x)))) (f 7))

它没有给我 49,而是通知我:

*** Eval error ***  Symbol's function definition is void: f

不知道为什么,我确信语法是正确的并且 f 是在 let 中定义的?

使用cl-flet定义let-ed函数

我们可以不使用 funcall 实际上做到这一点。 cl 模块包含来自 Common Lisp 的标准函数。我们首先导入它:

(require 'cl)

之后我们可以使用cl-flet来定义我们的函数:

(cl-flet ((f (x) (* x x)))
  (f 7))

最佳答案

如果这不是重复的,我会感到惊讶,但我无法在 Stack Overflow 上轻松找到它。在“Lisp-2”语言(例如 Emacs Lisp 和 Common Lisp)中,函数和变量有单独的命名空间。函数调用如下所示:

((lambda ...) ...) ; call the lambda function

(f ...) ; call the function binding of f

如果你想调用函数是一个变量的值,那么你需要使用funcall或apply:

(apply f ...)

(funcall f ...)

applyfuncall 之间的区别在其他地方有详细记录,但快速的区别是 apply 需要一个参数列表(在一些 Lisps,一个“可扩展的参数列表”),而 funcall 直接接受参数。例如,

(let ((f (lambda (a b) (+ a b))))
  (funcall f 1 2)      ; arguments directly
  (apply f '(1 2)))    ; arguments in a list

在“Lisp-1”(如 Scheme)中,您不需要 funcall,因为只有一个空间用于绑定(bind)。在 Scheme 中你可以做:

(let ((f (lambda (a b) (+ a b))))
  (f 1 2))

Lisp-1 和 Lisp-2 语言之间的差异在 What is the difference between Lisp-1 and Lisp-2? 中有更多描述。 .最大的区别是当系统看到函数调用时,它如何确定要调用的函数。在 Lisp-1 中,变量有值,仅此而已。因此,当系统看到类似以下内容时:

(f ...)

f是一个变量,唯一可能调用的是f的值。在 Lisp-2 中,系统尝试调用 f 的函数值,这与变量 f 的值没有任何关系。起初这可能有点令人困惑,但在很多情况下它实际上非常方便,因为它使得意外地混淆具有通用名称的函数变得更加困难。例如,在 Lisp-1 中,您会看到很多人使用 lst 作为参数名称而不是 list,因为如果他们将参数命名为 list,那么他们就不能在函数中使用(标准)函数 list

关于emacs - Elisp:在 Let 中绑定(bind)一个 lambda 并执行它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36039840/

相关文章:

用 knitr 编译后将 Emacs 缓冲区焦点返回到 R

python - 如何让 Aquamacs 在 ipython 中运行代码

emacs - 如何移动目录和其中的所有缓冲区?

emacs - 将 emacs 苹果酒连接到 vagrant 宿主 clojure 项目

emacs - 结合两个Emacs缓冲区?

haskell - Haskell 是否有类似于后期绑定(bind)的东西(或者,我们可以更改正在进行的 Haskell 程序的功能定义)吗?

string - Lisp - 将输入拆分为单独的字符串

data-structures - 如何使用结构成员类型进行散列?

function - emacs lisp 是否支持在词法上重新定义函数?

emacs - 在没有 ielm 模式的情况下评估 emacs 中的简单 elisp 缓冲区