Scheme 方案-使用延续

Scheme 方案-使用延续,scheme,continuation,Scheme,Continuation,所以我想我知道延续基本上是如何在Scheme中工作的,但我很难弄清楚如何使用它而不是递归 我们得到了makematcher的工作代码(只是基本的模式匹配),它已经完成了我们想要的一切。您给它一个模式,它会为您创建一个匹配器,您可以使用它在片段中搜索该模式。匹配器接受一个接受器,它将结果提供给该接受器,如果结果不被接受,它将递归地下降到片段的下一部分并继续进行 现在,我们要做的基本上是修改它,用连续体代替接受者。它返回后缀(模式中未匹配的剩余内容)和一个延续,类似 (let ((suffix (c

所以我想我知道延续基本上是如何在Scheme中工作的,但我很难弄清楚如何使用它而不是递归

我们得到了makematcher的工作代码(只是基本的模式匹配),它已经完成了我们想要的一切。您给它一个模式,它会为您创建一个匹配器,您可以使用它在片段中搜索该模式。匹配器接受一个接受器,它将结果提供给该接受器,如果结果不被接受,它将递归地下降到片段的下一部分并继续进行

现在,我们要做的基本上是修改它,用连续体代替接受者。它返回后缀(模式中未匹配的剩余内容)和一个延续,类似

(let ((suffix (car match-result))
          (backtrack (cdr match-result)))
将给我们后缀和一个函数回溯,我们可以调用它来继续

所以作为参考,原始代码

(define match-junk
  (lambda (k frag accept)
    (or (accept frag)
        (and (< 0 k)
             (pair? frag)
             (match-junk (- k 1) (cdr frag) accept)))))

(define match-*
  (lambda (matcher frag accept)
    (or (accept frag)
        (matcher frag
                (lambda (frag1)
                  (and (not (eq? frag frag1))
                       (match-* matcher frag1 accept)))))))

(define make-matcher
  (lambda (pat)
    (cond    
     ((symbol? pat)
      (lambda (frag accept)
        (and (pair? frag)
             (eq? pat (car frag))
             (accept (cdr frag)))))

     ((eq? 'or (car pat))
      (let make-or-matcher ((pats (cdr pat)))
        (if (null? pats)
            (lambda (frag accept) #f)
            (let ((head-matcher (make-matcher (car pats)))
                  (tail-matcher (make-or-matcher (cdr pats))))
              (lambda (frag accept)
                (or (head-matcher frag accept)
                    (tail-matcher frag accept)))))))

     ((eq? 'list (car pat))
      (let make-list-matcher ((pats (cdr pat)))
        (if (null? pats)
            (lambda (frag accept) (accept frag))
            (let ((head-matcher (make-matcher (car pats)))
                  (tail-matcher (make-list-matcher (cdr pats))))
              (lambda (frag accept)
               (head-matcher frag
                             (lambda (frag1)
                               (tail-matcher frag1 accept))))))))

     ((eq? 'junk (car pat))
      (let ((k (cadr pat)))
    (lambda (frag accept)
      (match-junk k frag accept))))

     ((eq? '* (car pat))
      (let ((matcher (make-matcher (cadr pat))))
    (lambda (frag accept)
      (match-* matcher frag accept)))))))
(定义匹配垃圾)
(lambda(k frag accept)
(或(接受frag)
(和(<0 k)
(配对?frag)
(匹配垃圾(-K1)(cdr frag)接受()())))
(定义匹配)-*
(lambda(匹配器框架接受)
(或(接受frag)
(火柴架)
(lambda(frag1)
(和(非(eq?frag frag1))
(匹配-*匹配器框架1接受(()()())))
(定义make matcher)
(兰姆达(帕特)
(续)
((符号?pat)
(lambda(frag接受)
(和(配对?frag)
(eq?pat(汽车碎片))
(接受(cdr框架(()())))
((等式?)或(车拍))
(让制造商或匹配者(pats(cdr pat)))
(如果(空?pats)
(lambda(frag accept)#f)
(让((头部匹配器(使匹配器(车拍)))
(尾部匹配器(制造或匹配器(cdr pats)))
(lambda(frag接受)
(或(头部匹配器框架接受)
(尾部匹配器框架接受(()()())))
((eq?列表(汽车pat))
(让制作列表匹配器((pats(cdr pat)))
(如果(空?pats)
(lambda(frag接受)(接受frag))
(让((头部匹配器(使匹配器(车拍)))
(尾部匹配器(制造列表匹配器(cdr pats)))
(lambda(frag接受)
(头部匹配器框架)
(lambda(frag1)
(尾部匹配器frag1接受(()()())()))
((等式?“垃圾”(汽车拍))
(让((k(cadr pat)))
(lambda(frag接受)
(匹配垃圾k碎片接受)
((等式?'*(汽车拍))
(让((匹配器)(使匹配器(cadr pat)))
(lambda(frag接受)
(match-*matcher frag accept(()()())))
让我们以or匹配器为例。此时,如果找到匹配项,它会将结果提供给接受者,如果接受者不喜欢结果,它会继续寻找下一个可能的答案。如果我想使用continuation,我必须在它找到结果后强制它退出,并使用call/cc存储程序的当前状态。我只是…不太确定我应该把逃生器放在哪里,然后打电话/cc。我想我现在需要添加一个基本情况,因为我没有一个接受者告诉我我的答案是对还是错,但是


我想如果有人能给我一些关于要做的主要改变的建议,我大概能弄明白。我正是在那里,我了解了其中的各个部分,却完全看不到如何实现它的大局。

让我们考虑它的方案。

您所需要的只是一个流,它逐个返回所有匹配项。您已经得到了一个函数,它会按顺序返回匹配项,如下所示:

(define matcher
  (lambda (yield)
    ; the following is your matcher implementation
    (loop ... (yield one-result) ...)))
yield是一个函数,它捕获延续并将控件返回给调用方。让我们通过call/cc实现它以生成流

(define make-match-stream
  (stream-unfold
    car                     ; map
    identify                ; pred
    (lambda (x) ((cdr x)))  ; gen
    (begin                  ; base
      (matcher (lambda (one-result)
        (call/cc (lambda (continuation)
          (cons one-result continuation)))))
      #f)))
stream unfold
来自srfi-41,它返回类似于
unfold
的流

使用
流过滤器
过滤掉不需要的结果:

(stream-filter accept result)