Scheme 先发制人——老练的阴谋家
请看第19章中的Scheme 先发制人——老练的阴谋家,scheme,continuations,callcc,seasoned-schemer,Scheme,Continuations,Callcc,Seasoned Schemer,请看第19章中的two-in-a-row*?函数 我的问题是关于get firsthelper函数中的(leave'())。请注意,(waddle l)将返回”()或一个atom,这表示列表已用尽或从列表中检索到一个atom 没有(leave'())它仍然会返回这两种值,只是不使用continuationleave。但是书上说没有(离开'())是不好的,我就是不明白为什么 (define two-in-a-row* (letrec ([leave id] ; the identity fun
two-in-a-row*?
函数
我的问题是关于get first
helper函数中的(leave'())
。请注意,(waddle l)
将返回”()
或一个atom,这表示列表已用尽或从列表中检索到一个atom
没有(leave'())
它仍然会返回这两种值,只是不使用continuationleave
。但是书上说没有(离开'())
是不好的,我就是不明白为什么
(define two-in-a-row*
(letrec ([leave id] ; the identity function
[fill id]
[waddle (lambda (l)
(cond [(null? l) '()]
[(atom? (car l))
(begin
(letcc rest
(set! fill rest)
(leave (car l)))
(waddle (cdr l)))]
[else
(begin
(waddle (car l))
(waddle (cdr l)))]))]
[get-first (lambda (l)
(letcc here
(set! leave here)
(waddle l)
(leave '()) ; why is this part needed???
))]
[get-next (lambda (l)
(letcc here
(set! leave here)
(fill 'go)))]
[T? (lambda (a)
(let ([n (get-next 'dummy)])
(if (atom? n)
(or (eq? a n)
(T? n))
#f)))])
(lambda (l)
(let ([fst (get-first l)])
(if (atom? fst)
(T? fst)
#f)))))
非常感谢
关于这个问题,另一个有趣的问题。命名看起来不合适。我用“屈服”表示“离开”,用“下一步”表示“填充”。我还必须定义
atom?
并将letcc
重新编写为call/cc
,以使其在Racket中工作。以下是完整的代码:
(define two-in-a-row*
(letrec ([yield '()]
[next '()]
[atom? (lambda (x) (and (not (null? x))
(not (pair? x))))]
[waddle (lambda (l)
(cond [(null? l) '()]
[(atom? (car l))
(begin
(call/cc (lambda ( here2 )
(set! next here2)
(yield (car l))))
(waddle (cdr l)))]
[else
(begin (waddle (car l))
(waddle (cdr l)))]))]
[get-first (lambda (l)
(call/cc (lambda ( here1 )
(set! yield here1)
(waddle l)
(yield '()) ; why is this part needed???
)))]
[get-next (lambda ()
(call/cc (lambda ( here3 )
(set! yield here3)
(next 'dummy))))]
[T? (lambda (a)
(let ([n (get-next)]) (display (list "next:" n))
(and (atom? n)
(or (eq? a n)
(T? n)))))])
(lambda (l)
(let ([a (get-first l)])
(and (begin (display (list "first:" a))
(atom? a))
(T? a))))))
我们可以在这里看到区别:
(two-in-a-row* '(((7) (b)) c (d)))
; w/out yield () : (first: 7)(next: b)(next: c)(next: d)(first: ())#f
; w/ yield () : (first: 7)(next: b)(next: c)(next: d)(next: ())#f
; w/ yield #f : (first: 7)(next: b)(next: c)(next: d)(next: #f)(next: #f)#t
(two-in-a-row* '(((7) (b)) c ()))
; w/out yield () : (first: 7)(next: b)(next: c)(first: ())#f
; w/ yield () : (first: 7)(next: b)(next: c)(next: ())#f
; w/ yield #f : (first: 7)(next: b)(next: c)(next: #f)(next: #f)#t
(two-in-a-row* '(((7) (b)) b ()))
; w/out yield () : (first: 7)(next: b)(next: b)#t
; w/ yield () : (first: 7)(next: b)(next: b)#t
; w/ yield #f : (first: 7)(next: b)(next: b)#t
谢谢威尔·内斯的例子。我看了一些更简单的。那么“这有什么不好的?”——没有
(离开“())
进入先获得
简短回答:请注意,从我的代码
i) 每次调用
get first
或get next
时,都会重新创建leave
。它将返回到get first
或get next
ii)
fill
将根据前面的fill
生成一个链,并且它将始终返回到get first
示例输入:
”(1)
因此,我们首先对'(1)
i) 设置离开 ii)启动
(摇摇晃晃)(1)
iii)由于
1
是一个原子,因此将fill
设置为当前延续。注意:如果我们使用fill
,那么它将转到do(waddle(cdr l))
,然后它将返回到get first
。
iv)使用返回值为1
的leave
返回到get first
然后我们转到eval(T?1)
,它将依次运行get next
i) 设置离开 ii)运行
填充
iii)启动(摇摇晃晃'())
iv)从waddle
返回()
,然后返回到get first
注意
1) 如果我们没有(离开“()”
,那么get first
将返回”()
,然后two-in-a-in-a-row*
返回#f
。因此我们可以得到相同的答案,但行为不是我们想要的。
2) 如果我们有它,那么请注意,leave
现在是由get next
创建的leave
,因此它将把()
转移到get next
3) 当我们创建fill
时,列表中有超过1个输入,它将基于先前的fill
创建,因此结果是一个链,取决于先前的fill这很棘手。书中的线索是哇代码>回复。学生在说哇因为他们意识到()
是从另一个函数返回的
这一点在书中或使用drracket都不清楚,我花了一段时间才理解,但理解这一点的关键是:
get first
调用waddle
使填充
继续李>
waddle
(不使用continuations时)返回到get first
但是
get next
调用fill
fill
在waddle
waddle
使用leave
返回到get next
而不是get first
但是在(waddle'())
的情况下,waddle
不使用leave
返回get next
。它正常返回。这意味着它将返回到get first
这意味着get next
实际上不会获取()
返回值。它不会获取此值,因为waddle
将返回到get first
现在是有趣的部分
我们知道,对于值()
,waddle
返回到get first
,当我们希望它返回到get next
时
我们知道get next
设置leave
返回get next
因此,get first
可以使用leave
返回到get next
这很棘手的真正原因是,当您在get first
中不使用(leave'())
时,请查看场景
用()
填充调用waddle李>
waddle
返回到get first
get first
然后返回()
这相当于:
(let ([fst '()]) ;; was (let ([fst (get-first l)])
(if (atom? fst)
(T? fst)
#f)))))
它返回的值与返回到get next
的版本的值相同:
[T? (lambda (a)
(let ([n '()]) ;; was (let ([n (get-next 'dummy)])
(if (atom? n)
(or (eq? a n)
(T? n))
#f)))])
两者都是#f
,但只是偶然!没有人说这本书不会让你思考;) 你好@Will Ness,太好了!!!我现在完全明白它的工作原理了。我会给你学分的。“我会把整个事情写在另一个答案里。”凌霄很高兴它对你有所帮助。这是一个真正令人心醉神迷的人