scheme - 为什么 The Little Schemer 的 (car (1 2)) 在 DrRacket 中不起作用?
问题描述
我一直在读《小谋士》的第一章。问题是,有些例子像 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...:
你能指出我为什么这些例子不起作用吗?
解决方案
这些示例不起作用,因为它们不是合法的方案。我对这本书不熟悉,但可能是它的排版方式可能会导致在不犯错误的情况下从其中转录示例有点困难。要了解为什么它们不是,您需要考虑系统如何评估事物。这是关于它如何工作的简单而部分的描述(实际的实现做的事情比这要复杂得多,而且这个描述是部分的,尤其是因为它根本没有解释我们如何获得事物的绑定)。
评估某事:
- 它是特殊的东西,比如字符串或数字或类似的东西,在这种情况下,它的值就是它自己;
- 它是一个符号,在这种情况下查找该符号的绑定,这就是值;
- 它是一种复合形式
(foo ...)
吗?如果是,那么——- 看看它的第一个元素:它是我们所知道的特殊魔法吗?如果是,则做适当的特殊事情(见下文);
- 否则以您喜欢的任何顺序评估复合形式的所有元素 - 第一个元素的值应该是一个函数,该值是将此函数应用于其余元素的值的结果。
所以我们可以使用这些规则来尝试评估(car ("a" "b"))
。
- 形式是复合形式,所以我们需要采取复合形式的情况;
car
不是什么特殊的东西,所以我们不打那个案子;- 因此,评估表单的元素(为简单起见,我将从左到右进行)-
car
是一个符号,所以查找它的值是一个函数;("a" "b")
是复合形式,它的第一个元素并不特殊——- 评估它的元素,这两个都是文字字符串,其值为本身;
- 现在尝试将第一个元素的值应用于所有其他元素的值,但失败了,因为它是字符串而不是函数。
好的,所以这行不通。为了使它起作用,我们需要返回并查看评估规则中的一个案例:当评估一个复合形式时,我们偷偷看一下第一个元素,以确定它是否是我们所知道的一些特殊的魔法事物,在这种情况下,我们会做一些特别的东西。这种特殊魔法的东西很少:我们这里唯一关心的是quote
。对此的特殊规则是:
- 如果我们看到一个复合形式,它的第一个元素是
quote
,它看起来像(quote ...)
,那么——- 它应该正好有两个元素,所以它应该看起来像
(quote <x>)
一些<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
to的值("a" "b")
,结果是"a"
。
所以还有一个技巧:经常(quote <x>)
出现,所以它有一个特殊的语法,它是一个单一的'
:与 .'x
读取相同(quote x)
。这只是使源代码不那么冗长。所以这给出了你正在尝试做的工作版本的最终形式:
(car '("a" "b"))
最后,Lisps需要 quote
的原因是一件有趣的事情,但与这个答案无关。
推荐阅读
- c# - .NET Core 3.1 控制台应用程序作为 Windows 服务
- sql-server - 循环 XML 数据
- jquery - 按钮上的toggleClass动态Jquery
- docker - 为什么 nginx 没有在 Windows Server 2019 docker 容器中启动?
- javascript - jQuery Ajax 多次提交表单
- flutter - 将 Row 固定到其他 UI 小部件顶部的 Scroll View 底部
- ruby - 在运行时将类添加到 ruby 模块
- typescript - 使用 ReturnType<> 时如何使属性可选
- google-maps - 如何使用矩形或多边形从给定区域的谷歌地图获取街道总数
- javascript - 移动 safari 过度滚动突然跳跃