在完成一些工作之后,我能够理解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.
我多次查看代码,但找不到错误。如果有人有任何见解,请分享。如果有人也可以通过一些好的例子向我指出(相对而言)温和的延续解释,那么也会非常感激。
如代码中的基本情况所示,您的收集器/继续必须采用3个参数。看来你传入了一个没有的功能。
你通过multirember&co
工作很好:我写了一个关于它的答案,which you may wish to review。
无论如何,测试这些收集器/延续的一般方法是首先使用list
作为延续,因为list
是可变参数并且只返回作为列表给出的项目。这是一个例子:
> (multiinsertLR&co 'foo 'bar 'baz '(foo bar baz qux quux) list)
'((foo foo bar baz foo qux quux) 1 1)
哦,我看到两个foo
s!插入哪一个,哪一个在原始列表中?
> (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
的每个分支,你会看到在左匹配情况,右匹配情况和不匹配情况下会发生什么(当然,结束 - 列表情况,设置基数/初始值)。注意在每种情况下如何发生插入(和计数器增量)。既然你已经获得了multirember&co
,那么从现在开始这应该是相当容易的。祝一切顺利!
这是我为解决克里斯的第二个例子所经历的过程,因为我认为这可能对其他可能被困的人有所帮助。 (如果有任何错误,请更正!)
;; 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
再次用我最喜欢的模式匹配伪代码重写这个,最近,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
所以L
是oldL
的lat
s计数; R
是oldR
中的lat
计数;和new
是一个特殊的元素,插入到正在构建的结果列表中,在oldR
的右边,以及输入原子列表oldL
中的lat
元素的左边:
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
就这样。有用的符号,很容易。