combine
必须映射使用二元运算符bin
减少列表,但如果找到任何未通过谓词exc
的值,并且如果找到任何值,则必须返回pred?
这样的值不能在列表上执行任何计算。
这是一个简单的延续问题。
#lang racket
(define (id x)
x)
(define (const x)
(lambda (_) x))
(define (combine pred? bin zero exc)
(call/cc
(lambda (exit)
(letrec
((f (lambda (xs)
(if (empty? xs)
zero
(if (pred? (first xs))
(exit exc)
(bin (first xs) (f (rest xs))))))))
f))))
(define product
(combine zero?
*
1
0))
(product '(1 2 3 0 4))
代码几乎可以工作,但它有一个非常微妙的错误。
它引发了以下异常:
define-values: assignment disallowed;
cannot re-define a constant
constant: product
很容易让它发挥作用。只需要做一些小改动:
(define (combine pred? bin un zero exc)
(lambda (ys)
(call/cc
(lambda (exit)
(letrec
((f (lambda (xs)
(if (empty? xs)
zero
(if (pred? (first xs))
(exit exc)
(bin (first xs) (f (rest xs))))))))
(f ys))))))
我看到问题是,Racket继续定义是定义一个函数,但任何人都可以提供更多细节吗?例如,涉及哪些合成转换?
答案 0 :(得分:1)
想想你必须拥有的顺序:
(define product (combine ....))
这里首先评估(combine ...)
,继续是程序的其余部分,首先将计算值存储为名称product
。调用继续从f
跳转到正好再次存储product
。
通过调用(product '(1 2 3 0 4))
,您正在重新定义product
,因为它是程序的延续,而call/cc
会捕获延续。
在你的第二次尝试中,你做了一个真正的重构,将它包装在lambda中,并用相同的参数调用f。它只是在call/cc
发生时延迟,因此包含在延续中。在此版本中,延续是(product ...)
之后的任何内容,而不是product
(define product ...)