何时在 Lisp 中使用 ' (或引号)?

2024-01-01

在读完 Lisp 入门书的主要部分后,我仍然无法理解特殊运算符是什么(quote)(或同等学历') 函数确实如此,但我见过的所有 Lisp 代码都是这样。

它有什么作用?


简短回答绕过默认评估规则并执行not计算表达式(符号或 s-exp),并按照键入的方式将其传递给函数。

长答案:默认评估规则

当调用常规(我稍后会介绍)函数时,将评估传递给它的所有参数。这意味着你可以这样写:

(* (+ a 2)
   3)

进而评估(+ a 2),通过评估a2. 符号的值a在当前变量绑定集中查找,然后替换。说a当前绑定到值 3:

(let ((a 3))
  (* (+ a 2)
     3))

我们会得到(+ 3 2), + 然后在 3 和 2 上调用,产生 5。我们的原始形式现在是(* 5 3)产量15。

Explain quote已经!

好吧。如上所示,函数的所有参数都会被求值,因此如果您想传递symbol a而不是它的价值,你不想评估它。 Lisp 符号可以兼作它们的值和在其他语言中使用字符串的标记,例如哈希表的键。

这是哪里quote假设您想从 Python 应用程序绘制资源分配情况,而是在 Lisp 中进行绘制。让你的 Python 应用程序执行如下操作:

print("'(")
while allocating:
    if random.random() > 0.5:
        print(f"(allocate {random.randint(0, 20)})")
    else:
        print(f"(free {random.randint(0, 20)})")
    ...
print(")")

给你的输出看起来像这样(稍微漂亮一些):

'((allocate 3)
  (allocate 7)
  (free 14)
  (allocate 19)
  ...)

记住我所说的quote(“勾选”)导致默认规则不适用?好的。否则会发生的是allocate and free被查找,我们不希望这样。在我们的 Lisp 中,我们希望做到:

(dolist (entry allocation-log)
  (case (first entry)
    (allocate (plot-allocation (second entry)))
    (free (plot-free (second entry)))))

对于上面给出的数据,将进行以下函数调用序列:

(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)

但是关于list?

嗯,有时候你do想要评估这些论点。假设您有一个漂亮的函数,可以操作数字和字符串并返回结果的列表……。让我们先做一个错误的开始:

(defun mess-with (number string)
  '(value-of-number (1+ number) something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))

嘿!那不是我们想要的。我们想有选择地评估一些论点,并将其他论点保留为符号。尝试#2!

(defun mess-with (number string)
  (list 'value-of-number (1+ number) 'something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)

不只是quote, But backquote

好多了!顺便说一句,这种模式在(大多数)宏中非常常见,因此有特殊的语法可以做到这一点。反引号:

(defun mess-with (number string)
  `(value-of-number ,(1+ number) something-with-string ,(length string)))

这就像使用quote,但可以选择通过在某些参数前加上逗号前缀来显式求值。结果相当于使用list,但是如果您从宏生成代码,您通常只想计算返回的代码的一小部分,因此反引号更适合。对于较短的列表,list可以更具可读性。

嘿,你忘了quote!

那么,这会给我们带来什么影响呢?哦,对了,什么是quote实际上呢?它只是返回未评估的参数!还记得我一开始所说的常规函数​​吗?事实证明,一些运算符/函数需要not评估他们的论点。例如 IF——如果 else 分支没有被采用,你不会希望它被评估,对吗?所谓的特殊操作员,与宏一起工作,就像这样。特殊运算符也是该语言的“公理”——最小的规则集——根据它,您可以通过以不同方式将它们组合在一起来实现 Lisp 的其余部分。

Back to quote, 尽管:

Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL

Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL

比较(在 Steel-Bank Common Lisp 上):

Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING   {A69F6A9}>:
  The variable SPIFFY-SYMBOL is unbound.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0] 

因为没有spiffy-symbol在目前的范围内!

加起来

quote, backquote(带逗号),以及list是一些用于创建列表的工具,它们不仅仅是值列表,而且如您所见,可以用作轻量级(无需定义struct) 数据结构!

如果你想了解更多,我推荐 Peter Seibel 的书实用 Common Lisp http://gigamonkeys.com/book如果您已经热衷于编程,可以了解学习 Lisp 的实用方法。最终,在您的 Lisp 之旅中,您也将开始使用包。罗恩·加勒特的Common Lisp 包白痴指南 http://www.flownet.com/ron/packages.pdf会给你很好的解释。

快乐黑客!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

何时在 Lisp 中使用 ' (或引号)? 的相关文章

  • Lisp 多次格式化一个字符

    我正在寻找一种输出字符的方法 多次使用格式 这可能吗 有人可以填写吗 在里面 的 这样这个例子就可以工作了吗 let n 3 format nil 应该返回 gt 很高兴看到这么多解决方案 到目前为止 A 迭代结构提供了一个简洁的解决方案
  • 调用另一个 lisp 文件中的函数

    我必须用 Lisp 写一个游戏 为了清楚起见 我想将代码拆分到不同的 lisp 文件中 如何从另一个文件中的函数中调用函数 例如 file1 lisp 有一个名为 function1 的函数 file2 lisp 有一个名为 functio
  • 内联定义函数与非内联函数有什么区别?

    我正在读这本书计算机程序的结构和实现 http mitpress mit edu sicp full text book book Z H 4 html在其中一章中 有一些代码用于计算数字的阶乘 define factorial n fac
  • Haskell、Lisp 和冗长[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 LISP 中如何检查闭包中的自由变量?

    在 lisp 中 我可以像这样绑定在闭包中绑定的自由变量 let x 1 y 2 z 3 defun free variables x y z free variables 结果是 6 我想知道是否可以动态检查绑定的闭包变量 E g ins
  • 与 emacs/slime 的其他 Lisp/Scheme 实现等效的 'lein swank'

    我一直在使用 emacs slime 来编码 lisp 但是使用 Clojure 我发现了 lein swank 我必须说它非常有用 因为我可以连接到运行 clojure 的服务器 其他 Lisp 实现怎么样 哪些 Lisp 实现提供了与
  • 在lisp中,如何使用floor函数返回的第二个值?

    当我这样做时 4楼3 我得到了 1 1 3 但我该如何使用这 1 3 呢 例如 您可以使用将其绑定到变量multiple value bind multiple value bind quot rem floor 4 3 format t
  • 在 LISP 中实现基本库函数(手动)

    有什么方法可以定义函数my list my cons my append其执行类似的功能list cons and append分别 否则哪里可以找到这些功能的实现呢 Thanks 对于my list和my append 解决方案是 def
  • 格式 - 帮助打印表格

    这个问题可能会以捂脸结束 但我已经尝试了一段时间 尽管阅读了超规范 但仍然卡住了 基本上我想做的是 format t 5d 1 23 2 312 23 456 1 7890 但不应该对 5 进行硬编码 而是应该从列表中计算 任何嵌套列表中最
  • Haskell 中的基因编程

    有 GenProg http hackage haskell org package genprog http hackage haskell org package genprog 例如 但这仅涉及数值优化 在本例中找到描述数据的方程 但
  • R 的 C API 中的 SEXP 数据类型到底是什么以及为什么使用它? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我知道关于 SEXP 的维基百科页面 并且我知道它代表符号表达 我 模糊地 知道 SEXP 是指 Lisp 中的树数据结构的符号 但我
  • 防止 LISP 中的终端输出

    我想运行一个函数 但不让它在终端中输出结果 例如 set A B 正常返回B在控制台中如下所示 gt gt gt set A B B gt gt gt A B 我不希望它返回任何东西 我仍然希望该函数能够完成它应该做的事情 只是默默地 gt
  • 如何克服 emacs lisp 闭包缺少局部变量的问题

    我现在正在学习 Emacs Lisp参考手册 http www gnu org software emacs manual elisp html和 Common Lisp 来自LISP https rads stackoverflow co
  • 在 Parenscript 中使用 regex(正则表达式)

    我正在尝试 Parenscript 在尝试使用正则表达式函数时 我得到了意外的输出 例如 参考手册 https common lisp net project parenscript reference html shows regex f
  • 任意类型说明符上的 Defmethod?

    我想做的是 defgeneric fn x defmethod fn x integer 1 Positive integer defmethod fn x integer 1 Negative integer 我想要一个可以与任意类型说明
  • 将列表传播到父代 sexp 中

    在任何 lisp 中是否有一种形式可以在父 sexp 中 传播 列表 喜欢 spread 1 2 3 gt 1 2 3 有两种方法可以做到这一点 哪个更好取决于您最终想要什么 一般来说 您可以使用 inside 反引号 表格如下 被评估以生
  • AmazonDB 免费套餐的含义是什么?

    在我的 Android 应用程序中 我使用 Amazon DynamoDB 我创建了 10 个表 读取容量为 10 写入容量为 5 今天我收到了一封来自 Amazon 的电子邮件 我花了 11 36 美元 我不明白免费套餐的含义 这是我从亚
  • Scheme 和 Racket 中嵌套引号的行为

    在 Racket 中编写函数时 我不小心在符号前面放了两个单引号而不是一个 即我不小心写了 a 并发现嵌套引号的一些行为看起来很奇怪 我正在使用 DrRacket 并使用 Racket lang 和 R5RS lang 对此进行了测试 wr
  • 在我的 Linux 机器上安装 lisp

    我使用 Vim 作为我的编辑器 Practical common Lisp 建议安装 Lispbox 我不知道如何使用 emacs 不知道如何用那个 T T 运行 lisp 代码 之后我找到了一个名为 limp vim 的 vim lisp
  • 为什么 LISP 中符号名称中的连字符是约定俗成的?

    这个推荐的理由是什么 为什么不与使用下划线的其他编程语言保持一致 我认为 LISP 使用连字符有两个原因 历史 和 因为你可以 History LISP 是一种古老的语言 在早期输入下划线可能会很困难 例如 我用于 LISP 的第一个终端是

随机推荐