Search code examples
recursionschemeracketr5rs

Dynamically fill a list with key value pairs


I need to fill a list with pairs, for example: ((x 10)(z 5)).

My current method:

;;send the current list, and an id value pair
(define (setID idList ID VAL)

  (cond 
        ;;if the list is null, add the pair
        ((null? idList) (cons '(ID VAL) '()))    

        ;; if the ID already exists, overwrite it
        ((equal? ID (car(car idList)))  (cons '((cdr idList)) VAL))

        ;; continue the search
        (else  (setID (cdr idList) ID VAL))
  )
)

I realize I also need to use cons to keep the list in tact, but the first problem is that when I do something like (setID z 5), the returned list is exactly: ((id val)). Obviously, it needs to be ((z 10)). Is there anyway to do such a thing?


Solution

  • There are three main problems with your code:

    • In here: (cons '(ID VAL) '())) you're building a new pair with the value (ID VAL) - that is, the first element is the symbol ID and the second is the symbol VAL. That's not what you want, you want the value of ID and the value of VAL. Make sure you understand the way a quote works
    • When you find an existing ID you have to cons the newly modified pair with the rest of the list
    • And even if the current pair isn't the one we're looking for, we also have to cons it to the output. Remember: we're building the answer as we go traversing the list

    This is what I mean:

    ;;send the current list, and an id value pair
    (define (setID idList ID VAL)
      (cond 
        ;;if the list is null, add the pair
        ((null? idList) (cons (list ID VAL) '()))
        ;; if the ID already exists, overwrite it
        ((equal? ID (car (car idList))) (cons (list ID VAL) (cdr idList)))
        ;; continue the search
        (else (cons (car idList) (setID (cdr idList) ID VAL)))))
    

    And don't forget that the list returned after executing this procedure is a new one, you have to store it somewhere or pass it along as a parameter if you want to keep adding elements to it - because the list originally received as parameter remains unmodified. Now the procedure works as expected:

    (setID '() 'x 10)
    => '((x 10))
    
    (setID '((x 10)) 'y 20)
    => '((x 10) (y 20))
    
    (setID '((x 10) (y 20)) 'x 30)
    => '((x 30) (y 20))