Scheme中的“set!not a identifier”

时间:2013-11-06 17:23:23

标签: object recursion scheme racket multiset

我正在尝试使用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))

2 个答案:

答案 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))