简体   繁体   English

方案 - 使用延续

[英]Scheme- using continuations

So I THINK I understand how continuations basically work in Scheme, but I'm having trouble figuring out how to use it instead of recursion. 所以我认为我理解continuation基本上如何在Scheme中工作,但我无法弄清楚如何使用它而不是递归。

We are given working code for make-matcher (just basic pattern matching) that already does everything we want it to. 我们获得了make-matcher(只是基本模式匹配)的工作代码,它已经完成了我们想要的所有工作。 You give it a pattern and it creates a matcher for you that you can use to search through fragments for that pattern. 你给它一个模式,它为你创建一个匹配器,你可以用来搜索该模式的片段。 The matcher takes an acceptor that it gives it's results to, and if the result isn't accepted, it recursively descends into the next part of the fragment and keeps going. 匹配器接受一个它给出结果的接受器,如果结果不被接受,它会递归地下降到片段的下一部分并继续运行。

Now, what we have to do is basically is modify it to use continuations instead of acceptors. 现在,我们要做的基本上是修改它以使用continuation而不是acceptrs。 It returns the suffix (left over stuff from the pattern that wasn't matched) and a continuation, so something like 它返回后缀(从未匹配的模式中留下的东西)和延续,所以类似于

(let ((suffix (car match-result))
          (backtrack (cdr match-result)))

Would give us the suffix and a function backtrack we could call to keep going. 会给我们后缀和函数回溯我们可以调用继续前进。

So for reference, the original code 所以供参考,原始代码

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

So let's use the or-matcher for an example. 所以让我们使用or-matcher作为例子。 At the moment if it finds a match, it gives the result to the acceptor and if the acceptor doesn't like the result, it continues on, looking for the next possible answer. 如果它找到匹配,它会将结果提供给接受者,如果接受者不喜欢结果,它会继续,寻找下一个可能的答案。 If I wanted to use continuation, I would have to force it to exit after it finds a result and use call/cc to store the current state of the program. 如果我想使用continuation,我必须强制它在找到结果后退出并使用call / cc来存储程序的当前状态。 I'm just...not exactly sure WHERE I should put the escape and call/cc. 我只是...不确定我应该放置转义和呼叫/ cc。 I think I need to add a base case now since I don't have an acceptor telling me if my answer is true or false but... 我想我现在需要添加一个基础案例,因为我没有接受者告诉我,如果我的答案是真是假,但......

I think if someone just gives me some pointers about the main changes to make, I can probably figure it out. 我想如果有人给我一些关于主要变化的指示,我可能会想出来。 I'm at that point where I understand the individual parts of WHAT but can't exactly see the big picture of how to implement it. 我正是在这一点上,我理解了WHAT的各个部分,但却无法准确地看到如何实现它的大局。

let's consider it scheme-way. 让我们考虑一下方案方式。

all you need is a stream, which return all matches one by one. 您只需要一个流,它将逐个返回所有匹配项。 and you already got an function which returns the matches sequential, like this one: 你已经有了一个返回匹配顺序的函数,就像这样:

(define matcher
  (lambda (yield)
    ; the following is your matcher implementation
    (loop ... (yield one-result) ...)))

yield is a function which capture the continuation and return the control to the caller. yield是一个捕获延续并将控件返回给调用者的函数。 let's implement it by call/cc to make a stream. 让我们通过调用/ 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 comes from srfi-41, which returns a stream like unfold does. stream-unfold来自srfi-41,它返回像unfold一样的流。

use stream-filter to filter out the result you don't need: 使用stream-filter过滤掉您不需要的结果:

(stream-filter accept result)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM