Emre Şimşirli
Emre Şimşirli

Reputation: 13

Updating a list without using set! - Scheme

I've a problem about keeping a list in the memory without using set!

I have an initial empty list defined,

(define database (list))

then I have this procedure which checks if the password is correct and adds the pair to the list.

(define (set-pass l)
  (if (pair? l)
    (if (check-pass (second (last l)))
      (add-to-list l) 
      "password does not meet policy requirements"
      )
  "invalid input"
  )
)

And a add-to-list procedure:

(define (add-to-list l)
  ;(append database l)
  ;implement this.
  )

Problem is, I have to call this procedure multiple times:

(set-pass '('john '(X p c F z C b Y h 1 2 3 4 : :)))
(set-pass '('john '(X p c F z C b Y : 1 2 3 4 : :)))
(set-pass '('john '(X p c F z C b : : 1 2 3 4 : :)))

I implemented the procedure add-to-list like I'm calling set-pass once (with append as shown above), but I couldn't find a way to implement if I call it multiple times. I tried a few things mentioned here, here and here. But I couldn't achieve what I wanted. So how can I do this?

Upvotes: 1

Views: 178

Answers (1)

Sylwester
Sylwester

Reputation: 48745

It's possible to do this functionally by having the database as a variable:

(let loop ((input (read-line)) (database '()))
  (display (format "inserting ~a\n" input))
  (loop (read-line)
        (cons input database)))

The other features (removing etc) work the same way you as recur with the altered structure according the operation.

You can also update a list with set-cdr!. While set! mutates what a symbol points to, set-cdr! mutates the cdr of a pair. Since it needs to be a pair you need to have the first element be some dummy data:

(define database (list "head"))

(define (add element)
  (let ((tmp (cdr database)))
    (set-cdr! database (cons element tmp))))

(define (delete element)
  (let loop ((prev database) (cur (cdr database)))
    (cond ((null? cur) #f)
          ((equal? (car cur) element) 
           (set-cdr! prev (cdr cur)))
          (else (loop cur (cdr cur))))))

(define (get)
  (cdr database))

(add 1)
(add 2)
(add 3)
(get) ; ==> (3 2 1)
(delete 2)
(get) ; ==> (3 1)

The second you allow mutation the cat is out of the bag and all mutation is available. Eg. you can make a mutable object with closures if set! is provided and you can get mutable bindings with boxes if set-car!/set-cdr! is provided.

Upvotes: 1

Related Questions