Strange behaviour of (push )

Started by Bat, November 05, 2003, 03:04:15 PM

Previous topic - Next topic

Bat

I have a database organised as association lists (relations) of registers, one for each individual, and each register itself contains an association list of pairs <field value>. So, for example, it would be:

(set 'people

'(p1 (name (john macy)) (age 45) (hobbies fishing reading jogging))

 (p2 (name (mary dickens)) (age 27) (hobbies knitting dancing watching-tv))

 (p3 (name (paul donkey)) (age 18) (hobbies kicking eating)))



Now, I need to be able to insert a value into the some field, for some person-register:



(define (insert value field-id register-id relation , register field new-field new-register)

  (set 'register (assoc register-id relation))

  (set 'field (assoc field-id register))

  (set 'new-field (push value field 1))                                  

  (set 'new-register (replace-assoc field-id register new-field))

  (replace-assoc register-id relation new-register))



It responds with an error message "list expected in function replace-assoc". It seems that 'push' does not return a list. (It makes no difference to use or not the second argument to push; it always returns the atom <value>.



When I replace '(push value field 1)' for '(cons (first field) (cons value (rest field)))' it works smoothly.



Any suggestions ?

BTW, how would you code it ?

Bat

#1
The correct code is:



(set 'people

'((p1 (name (john macy)) (age 45) (hobbies fishing reading jogging))

(p2 (name (mary dickens)) (age 27) (hobbies knitting dancing watching-tv))

(p3 (name (paul donkey)) (age 18) (hobbies kicking eating))))



(define (insert value field-id register-id relation , register field new-field new-register)

(set 'register (assoc register-id relation))

(set 'field (assoc field-id register))

(set 'new-field (cons (first field) (cons value (rest field)))) ; <-- here try push !

(set 'new-register (replace-assoc field-id register new-field))

(replace-assoc register-id relation new-register))



And it is called with:



(insert 'drinking 'hobbies 'p2 people)



The problem is when substitute "(push value field 1)" for

"(cons (first field) (cons value (rest field)))"



Why push does not work ?

Lutz

#2
As you already found out: 'push' in newLISP returns the element pushed. If you need the changed list returned use 'cons'. Note that push/pop also take a addtional position parameters, i.e: (push elmnt  mylist -1) would append the element to the end of the list.



You might also consider to do the job with symbols and contexts as outlined in the useres manual 'Arrays and hash tables in newLISP'. It largely depends on the size of your database and if you hit performance problems. For a few hundred I would stay with association lists, the way you are doing it, but beyond a few hundred, I would choose symbols for the handle (name) of the person and association lists for the attribute list of that person.



Note, that in newLISP v 7.2.8 the scoping rules are stricter when using contexts (which would make a job such as yours easier).



Lutz