scheme - 抢先 - 经验丰富的阴谋家

标签 scheme continuations callcc seasoned-schemer

请查看第 19 章中的 two-in-a-row*? 函数。

我的问题是关于 get-first 辅助函数中的 (leave '())。请注意,(waddle l) 将返回 '() 或一个原子,这表明列表已用完或从列表中检索到一个原子。

没有 (leave '()) 它仍然会返回这两种值,只是不使用延续 leave。但是书上说没有 (leave '()) 是不好的,我就是不明白为什么。

(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)))))

非常感谢。

另一个有趣的tread关于这个问题。

最佳答案

非常感谢 Will Ness 的示例。我检查了一些更简单的。那么“这有什么不好呢?” -- 在 get-first 中没有 (leave '())

简答:
请注意,从我的代码
i) 每次我们调用get-firstget-next 时,leave 总是会被重新创建。它将返回到 get-firstget-next
ii) fill 将根据之前的 fill 生成一个链,并且它总是返回到 get-first

例子
输入:'(1)

所以我们首先在 '(1) 上评估 get-first
i) 设置离开
ii) 开始 (waddle '(1)
iii) 由于 1 是一个原子,因此将 fill 设置为当前延续。注意如果我们使用fill,那么它会去执行(waddle (cdr l)),然后它会返回到get-first。 iv) 使用返回值 1leave 返回到 get-first

然后我们进入 eval (T? 1),这将依次运行 get-next
i) 设置离开
ii) 运行 fill
iii) 开始 (waddle '())
iv) 从waddle返回(),然后返回到get-first

注意
1) 如果我们没有(leave '(),那么get-first会返回'(),然后是 two-in-a-row* 返回#f。所以我们可以得到相同的答案,但行为不是我们想要的。
2) 如果我们有它,那么请注意 leave 现在是由 get-next 创建的 leave,因此它将转移 '()get-next
3) 当我们创建 fill 时,列表中有多个输入,它将根据之前的 fill 创建,因此结果是一个依赖于之前的 fill< 的链.

关于scheme - 抢先 - 经验丰富的阴谋家,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42044943/

相关文章:

scheme - 方案中的调用延续 CC

scheme - 为什么 scheme 不允许您从另一个函数中调用一个函数?

loops - 为什么在 Racket 代码中 for 循环如此缓慢

lambda - 在 Scheme 中消除 lambda?

python - 协程 vs 延续 vs 生成器

java - 如何避免 forkjoin 延续造成的线程局部损坏

scheme - 通话/抄送的细节

functional-programming - 如何在 Scheme/LISP 中编写除一体功能外的所有功能?

java - 检测客户端已与jetty服务器断开连接(使用延续)

haskell - 理解 Haskell callCC 例子