我正在尝试使用" define-syntax-rule"在球拍中创建我自己的while循环。 我希望它是基于程序的,所以没有辅助函数(即只使用lambda,let,letrec等)。
我有这个,但它给了我某种lambda标识符错误。
(define-syntax-rule (while condition body)
(lambda (iterate)
(lambda (condition body) ( (if condition)
body
iterate))))
我希望它能够像普通的while循环一样使用它 例如:
(while (x < 10) (+ x 1))
调用它将(应该)在循环完成后返回10。
我的代码如何修复才能执行此操作?
答案 0 :(得分:2)
以下是Standard Prelude中的while
及其使用示例:
Petite Chez Scheme Version 8.4
Copyright (c) 1985-2011 Cadence Research Systems
> (define-syntax while
(syntax-rules ()
((while pred? body ...)
(do () ((not pred?)) body ...))))
> (let ((x 4))
(while (< x 10)
(set! x (+ x 1)))
x)
10
您应该与您的导师讨论您对涉及Scheme的误解。
答案 1 :(得分:-1)
我无法决定这是否是家庭作业。所以,好吧,这是一个解决这个问题的版本:如果它是一个家庭作业,那么无论是谁设置它都可能是显而易见的,如果不是,那么它就是&#39有趣的是弄清楚它是如何工作的。
需要回答的一个问题是(while #f ...)
应评估的内容:通过说它应该评估为(void)
返回的内容来回答这个问题。这也使用(begin form ...)
进行排序:严重不正当会使用((λ () form ...))
而不是当然。
(define-syntax-rule (while condition form ...)
((λ (c) (c c (void)))
(λ (c v)
(if condition
(c c (begin form ...))
v))))
上述原始答案是故意混淆的,因为我不想提供作业答案。这是它的未经过仿冒的版本,以及一系列混淆/净化步骤,可以产生上述结果。
首先,我想要(while condition form ...)
做的是评估其中的表单,直到condition
不为真,然后返回最后一个表单的值。如果condition
永远不为真,请返回(void)
。
所以这样做的方法是使用循环,在Scheme中表达循环的一种非常自然的方式是命名为 - let
。剩下的技巧是返回的值绑定在命名的 - let
中,初始绑定为(void)
,后续的绑定是最后一个表单的结果,通过(begin form ...)
。所以,我们得到了这个:
(define-syntax-rule (while condition form ...)
(let loop ([v (void)])
(if condition
(loop (begin form ...))
v)))
你可以很清楚地看到它做了它需要做的事情。
所以,第一个混淆是我们不需要使用名为 - let
:我们可以使用letrec
代替:
(define-syntax-rule (while condition form ...)
(letrec ([loop (λ (v)
(if condition
(loop (begin form ...))
v))])
(loop (void))))
嗯,这显然做了同样的事情:letrec
建立了绑定值可见的绑定,所以这样可以正常工作。
但我讨厌letrec
:我们可以不使用它吗?是的,我们可以:我们可以传递这个东西来调用函数本身:
(define-syntax-rule (while condition form ...)
(let ([loop (λ (c v)
(if condition
(c c (begin form ...))
v))])
(loop loop (void))))
所以现在这个函数并不知道它自己在调用它:它只是给了一个函数来调用它本身。
最后一步是要意识到(let ((x y)) ...)
与((λ (x) ...) y)
相同:let
只是λ
上的一些语法糖。所以我们重写了以前的版本来获得这个:
(define-syntax-rule (while condition form ...)
((λ (loop) (loop loop (void)))
(λ (c v)
(if condition
(c c (begin form ...))
v))))
这是一些变量重命名,是原始版本。