1

我正在尝试使用 set! 修改列表元素的汽车的 cdr,但出现错误:“set!不是标识符”。谁能向我解释为什么会这样?顺便说一句,我开始使用对象。

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

4

2 回答 2

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)库中找到

于 2013-11-06T17:36:52.200 回答
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))
于 2013-11-06T19:10:14.240 回答