- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试解决 Structure and Interpretation of computer programming 问题 4.4 的最后一部分;任务是将 or 作为句法转换来实现。只定义了基本句法形式;引用、if、begin、cond、define、apply 和 lambda。
(或 a b ... c)等于第一个真值或假,如果没有值是真的。
我想要处理它的方式是将例如(或a b c)转换成
(if a a (if b b (if c c false)))
问题在于 a、b 和 c 将被计算两次,如果其中任何一个有副作用,则可能会给出不正确的结果。所以我想要一个类似 let 的东西
(let ((syma a))
(if syma syma (let ((symb b))
(if symb symb (let ((symc c))
(if (symc symc false)) )) )) )
这又可以像练习 4.6 中那样通过 lambda 实现。现在的问题是确定符号syma、symb 和symc;例如,如果表达式 b 包含对变量 syma 的引用,则 let 将破坏绑定(bind)。因此我们必须有 syma 是一个不在 b 或 c 中的符号。
现在我们遇到了障碍;我能从这个漏洞中看到的唯一方法是让符号不能出现在传递给 eval 的任何表达式中。 (这包括可能已通过其他句法转换传入的符号)。
但是因为我无法直接访问表达式中的环境,所以我不确定是否有任何合理的方法来生成此类符号;我认为 Common Lisp 具有用于此目的的函数 gensym(这意味着在 metacircular 解释器中保持状态,危及任何并发使用)。
我错过了什么吗?有没有办法实现或不使用 gensym?我知道 Scheme 有它自己的 hygenic macro 系统,但我还没有弄明白它是如何工作的,我不确定它下面是否有一个 gensym。
最佳答案
我认为您在这里可能想要做的是转换为句法扩展,其中不嵌套各种形式的计算。您可以这样做,例如,将每个表单包装为 lambda
函数,然后您使用的方法就可以了。例如,你可以做类似
(or a b c)
进入
(let ((l1 (lambda () a))
(l2 (lambda () b))
(l3 (lambda () c)))
(let ((v1 (l1)))
(if v1 v1
(let ((v2 (l2)))
(if v2 v2
(let ((v3 (l3)))
(if v3 v3
false)))))))
(实际上,lambda
函数的求值 调用 仍然嵌套在 if
和 let
中s,但是 lambda
函数的定义所在的位置使得在嵌套的 if
和 let
中调用它们不会导致捕获绑定(bind)的任何困难。)这没有解决如何您获取变量 l1
–l3
和 v1< 的问题
–v3
,但这并不重要,它们都不在 lambda
函数的范围内,因此您不需要担心它们是否出现在体内。事实上,您可以对所有结果使用相同变量:
(let ((l1 (lambda () a))
(l2 (lambda () b))
(l3 (lambda () c)))
(let ((v (l1)))
(if v v
(let ((v (l2)))
(if v v
(let ((v (l3)))
(if v v
false)))))))
此时,您实际上只是在执行更一般形式的循环展开,例如:
(define (functional-or . functions)
(if (null? functions)
false
(let ((v ((first functions))))
(if v v
(functional-or (rest functions))))))
(或 a b c)
的扩展就是
(functional-or (lambda () a) (lambda () b) (lambda () c))
此方法也用于 an answer至 Why (apply and '(1 2 3)) doesn't work while (and 1 2 3) works in R5RS? .而这一切都不需要任何 GENSYM
ing!
关于macros - SICP:可以或在 lisp 中定义为没有 gensym 的句法转换吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18284610/
我目前正在研究 SICP 关于逻辑编程的部分,但我被困在有关逻辑推导的示例中,尤其是附加到表单规则。它们是如何工作的?我不太明白的是第二条规则是如何取消第一个列表的。例如,给定: (规则(附加到表单(
据我了解,著名的SICP讲座视频: http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-struc
我已经以“边做边学”的方式编程了将近 2 年,我认为自己相当不错,但是,我真的希望为计算机科学/计算机工程打下良好的基础,大多数人建议我开始关闭 SICP。 (计算机程序的结构和解释) 我想知道 这是
我正在研究计算机程序的结构和解释。马上,有两个词被使用,似乎表示一些特定的概念:计算过程和程序。我有一个简单的问题。在 Abelson 和 Sussman 的用法上下文中,这些术语的定义是什么? 最佳
求值器完整实现代码我已经上传到了GitHub仓库: TinySCM ,感兴趣的童鞋可以前往查看。这里顺便强烈推荐UC Berkeley的同名课程 CS 61A 。 在这个层次结构
即使在变化中,它也丝毫未变。 ——赫拉克利特 吾犹昔人,非昔人也。 ——僧肇 前面我们介绍了组成程序的各种基本元素,看到了如何把基本过程和基本数据组合
绪论 我们在第一章引进复合过程时,采用了求值的代换模型定义了将过程应用于实参(arguments)的意义: 将一个复合过程应用于一些实参,也就意味着用实参替换过程体里对应的形参(f
绪论 我们已经介绍过数据抽象,这是一种构造系统的方法学,它能够使程序中的大部分描述与其所操作的数据对象的具体表示无关,比如一个有理数程序的设计与有理数的实现相分离。这里的关键是构筑数据抽象屏障
我在这里问了几个关于 Scheme/SICP 的问题,答案经常涉及使用 apply 过程,我在 SICP 中没有看到过,在本书的索引中,它只列出了一次,结果是脚注。 一些使用示例基本上是这个问题的每个
我目前正在通过计算机程序的结构和解释来完成本书和 Brian Harvey(他有时很搞笑)的讲座,但是我还没有真正拥有我的“啊哈!时刻”区分函数和程序。 现在,我在讲座和阅读之外进行了研究,发现了一些
关于 SICP 3.5 我自己的实现如下 (define (delay exp) (lambda () exp)) (define (force delayed-obj) (delayed-obj
考虑以下定义: (define foo (lambda (x y) (if (= x y) 0 (+ x (foo (+
我正在使用 SICP 书并且做了这个练习: 1.11 函数 f 由以下规则定义:如果 n 3. 编写一个通过递归过程计算 f 的过程。编写一个通过迭代过程计算 f 的过程。 递归过程很简单。迭代的更难
我在阅读 SICP 时遇到了一个问题,在第 1 章中有一个名为 counting change 的示例,我需要在 scheme 中编写一个程序来计算给定一半的任何给定数字的可能变化方式- 美元、25
我正在使用 SICP 这本书,我正在为递归与迭代过程的概念而苦苦挣扎。在问题 1.17 他们问这个: 练习 1.17。本节中的取幂算法基于通过重复乘法执行取幂。类似地,可以通过重复加法来进行整数乘法。
在关于不动点的第 1 章中,书上说我们可以使用以下方法找到某些函数的不动点 f(x) = f(f(x)) = f(f(f(x))) .... 那些功能是什么? 当我将它重写为 y = y/2 时它对
我正在学习 SICP 这本很棒的书。尽管很棒,但它确实是一本难懂的书。我遇到了长尾递归问题,id est,迭代过程的递归定义。 这本书介绍了阶乘的迭代过程: (define (factorial n)
我正在使用 SICP 这本书并尝试解决这个练习: 1.2.4 Exponentiation Exercise 1.18. Using the results of exercises 1.16 and
这是生成递归过程的 SICP 的阶乘过程。 (define (factorial n) (if (= n 1) 1 (* n (factorial (- n 1)))))
这个问题在这里已经有了答案: SICP recursive process vs iterative process: using a recursive procedure to generate
我是一名优秀的程序员,十分优秀!