Question

I am trying to modify the cdr of the car of an element of a list using set!, but I am getting an error: "set! not an identifier". Can anyone explain to me why this is happening? I am starting to work with objects by the way.

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

A multiset is represented as a list of pairs. For example, if I had a list '(1 1 1 2 2 2), the multiset representation would be '((1.3)(2.3))

Was it helpful?

Solution

The syntax of set! is

  (set! <identifier> <expression>)

which is to say that the first form must be a symbol. In your code you are using:

(cdr (car main-list))

as the 'identifier' - hence the error.

Perhaps your background is CommonLisp and you are expecting set! to behave like setf? In Scheme there are separate functions for setting the 'car' and 'cdr' of a pair. Use set-car! and set-cdr!

> (define pair (cons 'car 'cdr))
> pair
(car . cdr)
> (set-car! pair 'foo)
> pair
(foo . cdr)
> (set-cdr! pair 'bar)
> pair
(foo . bar)

In R6RS (and probably R7RS) set-car! and set-cdr! can be found in the (rnrs mutable-pairs) library

OTHER TIPS

GoZoner has given you the right explanation, but it is perfectly possible (and desirable) do avoid set! procedures. Here's an example of a procedure having the same result:

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

such as

(rle '(1 1 1 2 2 2))
=> '((1 . 3) (2 . 3))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top