为什么 The Little Schemer 中的 (car (1 2)) 在 DrRacket 中不起作用?

Why (car (1 2)) from The Little Schemer does not work in DrRacket?

我一直在阅读"The Little Schemer"的第一章。问题是,一些示例在 DrRacket 中工作,例如 (eq? "foo" "foo"),而有些示例不喜欢 (car ("a" "b"))(cdr ("a" "b")) 因为

application: not a procedure;
 expected a procedure that can be applied to arguments
  given: "a"
  arguments...:

你能指出为什么这些示例不起作用吗?

这些示例不起作用,因为它们不是合法的 Scheme。我对这本书不熟悉,但可能是因为它的排版方式可能会稍微难以转录其中的示例而不会出现您犯的错误。要了解为什么它们不是,您需要考虑系统如何评估事物。这是一个头脑简单的部分描述,说明它可能如何工作(实际实现做的事情比这更复杂,而且这个描述是部分的,尤其是因为它根本没有解释我们如何获得事物的绑定)。

评价某事:

  • 它是不是像字符串或数字之类的特殊东西,在这种情况下它的值就是它本身;
  • 它是一个符号,在这种情况下查找该符号的绑定,这就是值;
  • 是像(foo ...)这样的复合形式吗?如果是,那么——
    • 看看它的第一个元素:它是我们所知道的特殊魔法吗?如果是,则执行适当的特殊操作(见下文);
    • 否则以您喜欢的任何顺序评估复合形式的所有元素——第一个元素的值应该是一个函数,并且该值是将此函数应用于其余元素的值的结果。

所以我们可以使用这些规则来尝试评估(car ("a" "b"))

  • 表格是复合表格,所以我们需要取复合表格的大小写;
  • car 不是什么特别的东西,所以我们不碰那种情况;
  • 因此,评估表单的元素(为简单起见,我将从左到右进行)–
    • car是一个符号,所以查找它的值是一个函数;
    • ("a" "b")是复合形式,它的第一个元素并不特殊——
      • 对其元素进行求值,这两个元素都是字面字符串,其值为自己;
      • 现在尝试将第一个元素的值应用于所有其他元素的值,但失败了,因为它是字符串而不是函数。

好的,所以这行不通。为了让它发挥作用,我们需要回头看看评估规则中的一个案例:当评估一个复合形式时,我们偷偷看一下第一个元素,以确定它是否是我们知道的一些特殊的魔法事物,在那种情况下我们知道一些特别的东西。这种特殊魔法的东西很少:我们在这里唯一关心的是 quote。特殊规则是:

  • 如果我们看到第一个元素是 quote 的复合形式,它看起来像 (quote ...),那么 –
    • 它应该恰好有两个元素,所以对于某些 <x>;
    • 它应该看起来像 (quote <x>)
    • 表格的值为 <x> ,没有进一步尝试评估 <x>

因此,例如:

  • (quote x)的值是符号x;
  • (quote (1 2 3))的值是列表(1 2 3);
  • (quote "x") 的值是字符串 "x" (在这种情况下你不需要 quote ,因为字符串已经根据上面的第一条规则评估自己,但是不疼)。

所以回到我们想要评估的形式,我们实际需要的是(car (quote ("a" "b")))。评估时:

  • 表格是复合表格,所以我们需要取复合表格的大小写;
  • car 不是什么特别的东西,所以我们不碰那种情况;
  • 因此,评估表单的元素(为简单起见,我将从左到右进行)–
    • car是一个符号,所以查找它的值是一个函数;
    • (quote ("a" "b")) 是复合形式 –
      • 它的第一个元素特殊的,因为它是quote;
      • 所以使用 quote 的规则,结果是 ("a" "b");
    • 现在将car的值应用到("a" "b"),结果是"a"

所以还有一个技巧:(quote <x>) 经常出现,所以有一个特殊的语法,它是一个 ''x 读起来与 (quote x)。这只会使源代码不那么冗长。所以这给出了你正在尝试做的工作版本的最终形式:

(car '("a" "b"))

最后,Lisps 需要 quote 的原因值得思考,但这个答案离题了。