我正在尝试使用set!修改列表元素的汽车的cdr,但是我收到一个错误:“设置!不是标识符”。任何人都可以向我解释为什么会这样吗?顺便说一下,我开始使用对象。
#lang racket
(define (multiset)
(let ((main-list '()))
(define (empty)
(eq? main-list '()))
(define (insert x)
(cond ((empty)
(set! main-list (cons (cons x 1) main-list)))
((= (car (car main-list)) x)
(begin (set! (cdr (car main-list))
(+ 1 (cdr (car main-list))))))
(else (cdr main-list))))
多重集表示为对的列表。例如,如果我有一个列表'(1 1 1 2 2 2),多重表示将是'((1.3)(2.3))
答案 0 :(得分:3)
set!
的语法是
(set! <identifier> <expression>)
也就是说第一个表格必须是符号。在您使用的代码中:
(cdr (car main-list))
作为'标识符' - 因此错误。
也许您的背景是CommonLisp,并且您希望set!
的行为类似于setf
?在Scheme中,有一些单独的函数用于设置一对的'car'和'cdr'。使用set-car!
和set-cdr!
> (define pair (cons 'car 'cdr))
> pair
(car . cdr)
> (set-car! pair 'foo)
> pair
(foo . cdr)
> (set-cdr! pair 'bar)
> pair
(foo . bar)
在R6RS(可能是R7RS)set-car!
和set-cdr!
可以在(rnrs mutable-pairs)
库中找到
答案 1 :(得分:3)
GoZoner给了你正确的解释,但完全可能(并且可取)避免设置!程序。以下是具有相同结果的过程示例:
(define (rle lst)
(define (newpair c l res)
(if (> l 0) (cons (cons c l) res) res))
(let loop ((lst lst) (c #f) (l 0) (res '()))
(if (null? lst)
(reverse (newpair c l res))
(let ((n (car lst)))
(if (equal? c n)
(loop (cdr lst) c (add1 l) res)
(loop (cdr lst) n 1 (newpair c l res)))))))
,例如
(rle '(1 1 1 2 2 2))
=> '((1 . 3) (2 . 3))