此程序获取元素重复的列表,例如L = (a a a b b b c c c d)
,并输出项目列表和重复次数,例如((a 3)(b 3)(c 3) d)
(define counter 0)
(define (compress liste)
(if (or (null? liste) (null? (cdr liste)))
liste
(let ((compressed-cdr (compress (cdr liste))))
(if (equal? (car liste) (car compressed-cdr))
((+ counter 1) compressed-cdr)
((cons (car liste) counter) (= counter 0) (compressed-cdr))))
))
但是,出现此错误:
错误:应用程序:不是过程;期望可以应用于参数的过程给定:1个参数...
错误是第二个if条件的真实谓词。
为简单起见,使用“头部前哨把戏”以自上而下的方式构建结果列表:
(define (rle lst)
(if (null? lst)
'()
(let ((res (list 1))) ; head sentinel
(let loop ((p res) ; result's last cons cell
(elt (car lst))
(cnt 1)
(lst (cdr lst)))
(if (and (not (null? lst))
(equal? elt (car lst)))
(loop p elt (+ cnt 1) (cdr lst))
(begin
(set-cdr! p (list (if (= 1 cnt) elt (list elt cnt))))
(if (null? lst)
(cdr res) ; skip the head in result, on return
(loop (cdr p) (car lst) 1 (cdr lst)))))))))
如@uselpa所解释,这称为游程编码;为了保证结果的一致性,我建议对非重复元素使用(x 1)
表示形式。
以及错误“错误:应用程序:不是过程;应为过程”,正如其他人所说,意味着系统希望找到过程但发现了其他东西,因此无法应用它。 Scheme希望找到一个过程作为列表中的第一种形式:(proc args ...)
,并尝试将其应用于参数。但是在您的代码中,它不是过程,而是其他类型的数据。
如果您的方案已左折或reduce
,则可以执行两次-首先收集统一的结果,然后在反转时应用特殊格式(左折的结果通常按相反顺序构建:]]
(define (fold f init lst) ; if fold is not defined,
(reduce f init (cons init lst))) ; define it in terms of reduce
(define (rle lst)
(fold (lambda (x acc) ; NB! MIT-Scheme: (acc x)
(if (= 1 (cadr x)) (cons (car x) acc) (cons x acc)))
'()
(fold (lambda (x acc) ; NB! MIT-Scheme: (acc x)
(if (or (null? acc) (not (equal? (caar acc) x)))
(cons (list x 1) acc)
(cons (list x (+ (cadar acc) 1)) (cdr acc))))
'()
lst)))
如错误消息所述,问题位于“第二个if条件的真实谓词上:”
我很难弄清楚代码中的问题所在。我尝试了以下似乎可行的方法。