3

经过一些工作后,我能够理解该multirember&co功能,但我无法从以下multiinsertLR&co代码中真正理解(第 143 页):

(define multiinsertLR&co
  (lambda (new oldL oldR lat col)
    (cond
     ((null? lat)
      (col '() 0 0))
     ((eq? (car lat) oldL)
      (multiinsertLR&co
       new
       oldL
       oldR
       (cdr lat)
       (lambda (newlat L R) 
         (col (cons new
                    (cons oldL newlat))
              (add1 L) R))))
     ((eq? (car lat) oldR)
      (multiinsertLR&co
       new
       oldL
       oldR
       (cdr lat)
       (lambda (newlat L R)
         (col (cons oldR
                    (cons new newlat))
              L (add1 R)))))
     (else
      (multiinsertLR&co
       new
       oldL
       oldR
       (cdr lat)
       (lambda (newlat L R)
         (col (cons (car lat)
                    newlat) L R)))))))

这本书似乎没有解释collector在评估函数时最初应该通过哪一个,所以我分别使用了第 138 页和第 140 页上解释的a-friend收集器和收集器。last-friend使用任一收集器评估函数会导致以下错误(使用带有 petit chez 方案的跟踪函数):

>> (multiinsertLR&co 'salty 'fish 'chips '(chips and fish or fish and chips) last-friend)

|(multiinsertLR&co salty fish chips (chips and fish or fish and chips)
   #<procedure>)
|(multiinsertLR&co salty fish chips (and fish or fish and chips)
   #<procedure>)
|(multiinsertLR&co salty fish chips (fish or fish and chips) #<procedure>)
|(multiinsertLR&co salty fish chips (or fish and chips) #<procedure>)
|(multiinsertLR&co salty fish chips (fish and chips) #<procedure>)
|(multiinsertLR&co salty fish chips (and chips) #<procedure>)
|(multiinsertLR&co salty fish chips (chips) #<procedure>)
|(multiinsertLR&co salty fish chips () #<procedure>)
Exception: incorrect number of arguments to #<procedure>
Type (debug) to enter the debugger.

我查看了几次代码,但找不到错误。如果有人有任何见解,请分享。如果有人也可以通过一些好的例子向我指出(相对而言)对延续的温和解释,那也将不胜感激。

4

3 回答 3

3

这是我为解决 Chris 的第二个示例所经历的过程,因为我认为这可能对可能被卡住的其他人有所帮助。(如有错误请指正!)

;; Anonymous functions (collectors) in mutliinsertLR&co here defined as named  
;; functions for reference purposes
(define left-col
  (lambda (newlat L R)
    (col (cons new
               (cons oldL newlat))
         (add1 L) R)))              ; L counter gets incremented

(define right-col
  (lambda (new lat L R)
    (col (cons oldR
               (cons new newlat))
         L (add1 R))))              ; R counter gets incremented

(define else-col
  (lambda (newlat L R)
    (col (cons (car lat)
               (newlat) L R))))     ; neither counter gets incremented

;; Let's step through an example to see how this works:
;;
;; 1. ENTRY TO FUNCTION
;; new  = foo
;; oldL = bar
;; oldR = baz
;; lat  = (goo bar baz qux quux)
;; col  = list
;;
;; 1. Is lat null? No.
;; 2. Is car of lat equal to oldL? No.
;; 3. Is car of lat equal to oldR? No.
;; 4. Else? Yes. Recur on the function passing the new, oldL
;;    oldR, (cdr lat) and the new collector.
;;
;; 2. FIRST RECURSIVE STEP
;; new  = foo
;; oldL = bar
;; oldR = baz
;; lat  = (bar baz qux quux)
;; col  = else-col
;;
;; - Is lat null? No.
;; - Is car of lat equal to oldL? Yes. Recur on the function
;;   passing new, oldL, oldR, (cdr lat), and the new col.
;;
;; 3. SECOND RECURSIVE STEP
;; new  = foo
;; oldL = bar
;; oldR = baz
;; lat  = (baz qux quux)
;; col  = left-col
;;
;; - Is lat null? No.
;; - Is car of lat equal to oldL? No.
;; - Is car of lat equal to oldR? Yes. Recur on the function
;;   passing new, oldL, oldR, (cdr lat), and the new col.
;;
;; 4. THIRD RECURSIVE STEP
;; new  = foo
;; oldL = bar
;; oldR = baz
;; lat  = (qux quux)
;; col  = right-col
;;
;; - Is lat null? No.
;; - Is car of lat equal to oldL? No.
;; - Is car of lat equal to oldR? No.
;; - Else? Yes. Recur on the function passing new, oldL, oldR,
;;   (cdr lat) and the new collector.
;;
;; 5. FOURTH RECURSIVE STEP
;; new  = foo
;; oldL = bar
;; oldR = baz
;; lat  = (quux)
;; col  = else-col
;;
;; - Is the lat null? No.
;; - Is the car of lat equal to oldL? No.
;; - Is the car of lat equal to oldR? No.
;; - Else? Yes. Recur on the function passing new, oldL, oldR,
;;   (cdr lat) and the new collector.
;;
;; 6. FIFTH RECURSIVE STEP
;; new  = foo
;; oldL = bar
;; oldR = baz
;; lat  = ()
;; col  = else-col
;;
;; - Is the lat null? Yes. Call else-col, where newlat is (),
;;   L is 0 and R is 0.
;;
;; 7. ELSE-COL
;; newlat = ()
;; L      = 0
;; R      = 0
;; col    = else-col
;;
;; - Now call else-col on the (cons (car lat)), which is currently
;;   stored in memory as the atom "quux", onto newlat, as well as
;;   L and R.
;;
;; 8. ELSE-COL (again)
;; newlat = (quux)
;; L      = 0
;; R      = 0
;; col    = right-col
;;
;; - Now call right-col on the (cons (car lat)), which is currently
;;   stored in memory as the atom "qux", onto newlat, as well as L
;;   and R.
;;
;; 9. RIGHT-COL
;; newlat = (qux quux)
;; L      = 0
;; R      = 0
;; col    = left-col
;;
;; - Now call left-col on the cons of oldR and (cons new newlat),
;;   as well as L and the increment of R.
;;
;; 10. LEFT-COL
;; newlat = (baz foo qux quux)
;; L      = 0
;; R      = 1
;; col    = else-col
;;
;; - Now call else-col on the cons of new and (cons oldL newlat),
;;   as well as the increment of L and R.
;;
;; 11. ElSE-COL (last time)
;; newlat = (foo bar baz foo qux quux)
;; L      = 1
;; R      = 1
;; col    = list
;;
;; - Now we call list on the (cons (car lat)), which is currently
;;   stored in memory as the atom "goo", onto newlat, as well as L
;;   and R.
;; - This gives us the final, magical list:
;;   ((goo foo bar baz foo qux quux) 1 1)
;;
;; 12. FIFTH RECURSIVE STEP (redux)
;; new  = foo
;; oldL = bar
;; oldR = baz
;; lat  = (quux)
;; col  = else-col
;;
;; - Base case evaluated, with the result being
;;   ((goo foo bar baz foo qux quux) 1 1).
;; - Function ends.
;;
;; THE END
于 2012-09-01T04:52:51.107 回答
2

如代码中的基本情况所示,您的收集器/延续必须采用 3 个参数。看来您传入了一个没有传入的函数。


很高兴你完成了multirember&co:我写了一个关于它的答案,你可能希望查看它。

无论如何,测试这些收集器/延续的一般方法是首先使用list作为你的延续,因为list它是可变的并且只是返回作为列表给出的项目。这是一个例子:

> (multiinsertLR&co 'foo 'bar 'baz '(foo bar baz qux quux) list)
'((foo foo bar baz foo qux quux) 1 1)

哦,我看到了两个foos!插入了哪个,哪个在原始列表中?

> (multiinsertLR&co 'foo 'bar 'baz '(goo bar baz qux quux) list)
'((goo foo bar baz foo qux quux) 1 1)

啊,所以我们开始做点什么了!每当列表包含bar,时,foo都会在它之前插入;并且只要列表包含一个baz,foo就会在它之后插入。但是数字呢?

> (multiinsertLR&co 'foo 'bar 'baz '(baz goo bar baz qux bar quux baz) list)
'((baz foo goo foo bar baz foo qux foo bar quux baz foo) 2 3)

这些数字看起来像计数器!每个“左”插入增加第一个计数器,每个“右”插入增加第二个计数器。


在查看代码时,如果查看 的每个分支cond,您将看到左匹配情况、右匹配情况和不匹配情况(当然还有结束-list case,它设置基本/初始值)。注意在每种情况下插入(和计数器增量)是如何发生的。既然你已经得到了multirember&co,从这里开始这应该相当容易。一切顺利!

于 2012-08-31T14:42:03.717 回答
0

最近再次用我最喜欢的模式匹配伪代码重写它,1我们得到了更紧凑和视觉上更明显

multiinsertLR&co new oldL oldR lat col  =  g lat col 
  where
  g [a, ...t] col 
    | a == oldL  =  g t  ( newlat L R =>  col [new, oldL, ...newlat] (add1 L)  R  )
    | a == oldR  =  g t  ( newlat L R =>  col [oldR, new, ...newlat]  L  (add1 R) )
    | else       =  g t  ( newlat L R =>  col [a,         ...newlat]  L        R  )
  g [] col       =                        col []                      0        0

中sL的计数也是如此;是s 中的计数;and是一个特殊元素,它被插入到正在构建的结果列表中,在输入原子列表中的元素的右侧和左侧:oldLlatRoldRlatnewoldRoldLlat

multii&co 0 1 2 [1,4,5,2,4,5,1,4,5,1] col 
=
col [0,1,4,5, 2,0,4,5, 0,1,4,5, 0,1 ] 3 1

就这样。使用有用的符号,这很容易。


1看到这个这个

于 2018-01-24T19:45:18.733 回答