gpt4 book ai didi

lisp - 仍然关于 Lisp 中的引用

转载 作者:太空宇宙 更新时间:2023-11-03 18:56:20 26 4
gpt4 key购买 nike

我是Lisp的新手,业余时间慢慢学习......几个月前,我对Lisp REPL的错误报告感到困惑,以下表达式不起作用:

((if (> 2 1) + -) 1 2)

环顾四周,我知道 Lisp 不是 Scheme...在 Lisp 中,我需要做任何一个:

(funcall (if (> 2 1) '+ '-) 2 1), 或者

(funcall (if (> 2 1) #'+ #'-) 2 1)

我还瞥了一眼关于 lisp-1 和 lisp-2 的介绍 Material ,虽然我无法完全理解那里的所有内容......无论如何,我知道 quote 阻止评估,作为评估规则的异常(exception)。

最近我正在阅读一些关于 reduce 的内容...然后作为练习,我想编写我自己的 reduce 版本。虽然我设法让它工作(至少它看起来工作),但我意识到我仍然无法准确解释为什么在 defun 的主体中,有些地方 funcall 是需要,但在某些地方不需要。

下面是elisp中的myreduce:

    (defun myreduce (fn v lst)
(cond ((null lst) v)
((atom lst) (funcall fn v lst))
(t (funcall fn (car lst) (myreduce fn v (cdr lst))))))

(myreduce '+ 0 '(1 2 3 4))

我的问题是关于第 3 行和第 4 行:

  1. 第三行:为什么我需要funcall?为什么不只是 (fn v lst)?我的“论点”是,在 (fn v lst) 中,fn 是列表中的第一个元素,因此 lisp 可以使用此位置信息将其视为一个功能......但它不是。所以我肯定在这里错过了一些东西。

  2. myreduce 的递归调用中的第 4 行:什么样的 fn 被传递给 myreduce 的递归调用? '++,还是其他?

我想应该有一些我不知道的非常基本的东西......我想知道,当我调用 myreduce 时,如第 6 行/最后一行所示,之后究竟发生了什么(至少关于 '+ 是如何传递的),有没有办法在任何 REPL 环境中跟踪它?

非常感谢,

/熊

最佳答案

Common Lisp 是 LISP-2,有两个命名空间。一种用于函数,一种用于变量。参数绑定(bind)在变量命名空间中,因此函数命名空间中不存在 fn

(fn arg) ; call what fn is in the function namespace
(funcall fn ...) ; call a function referenced as a variable

'+ 是一个符号,funcallapply 会在它看到它是一个符号而不是时在全局函数命名空间中查找它一个函数对象。 #'+(function +) 的缩写,它从本地函数命名空间解析函数。对于大量调用,#'+'+ 更快,因为 '+ 需要查找。符号和函数都可以作为 fn 传递给 myreduce,传递的内容与第 4 行中传递的内容相同。

(myreduce '+ 0 '(1 2 3 4)) ; here funcall might lookup what '+ is every time (CLISP does it while SBLC caches it)
(myreduce #'+ 0 '(1 2 3 4)); here funcall will be given a function object looked up in the first call in all consecutive calls

现在,如果您传递 '+,它将被评估为 + 并绑定(bind)到 fn。在 myreduce 中,我们在递归中传递了 fn,它也会被计算为 +

对于 #'+,它计算函数并绑定(bind)到 fn。在 myreduce 中,我们在递归中传递 fn,它将被评估为 fn 绑定(bind)到变量命名空间中的函数对象。

Common Lisp 已将构造添加到函数命名空间中。例如。

(flet ((double (x) (+ x x))) ; make double in the function namespace
(double 10)) ; ==> 20

但您可以编写它并在变量命名空间上使用它:

(let ((double #'(lambda (x) (+ x x)))) ; make double in the variable namespace
(funcall double 10))

关于lisp - 仍然关于 Lisp 中的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20195831/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com