From: Pascal J.B. <pj...@in...> - 2005-04-27 19:49:46
|
Andreas Schmid writes: > Hi there, > > I've got a problem with code that used to work with a different implementation > of Common Lisp. Unfortunately it doesn't now with clisp. > > The idea of the code is to build a database of facts. It works just fine if the > database is non-empty, i.e. it already contains a fact. When starting with an > empty list, however, it seems to be impossible to add the first element to it > AND retain it. Here are the two functions involved and the dribble: > [...] > (defun make-db () > (format t "Empty database created:") > ()) > [...] > (defun add-fact (database new-fact) > (cond > ((null new-fact) (format t "List contains no data. Nothing added to database.")) > ((atom new-fact) (format t "Fact should be a list.")) > ((listp new-fact) (format t " Adding to database:~% ~A~%" database) > (if (null database) > (progn (setf database (list new-fact)) > (format t " Database empty!")) > (setf (rest database) (cons new-fact (rest database)))) > new-fact) > (t (format t "Fact should be a list."))) > database) Everything is either an ATOM or a CONS. Every list is either NIL or a CONS. Therefore: (cond ((null x) ...) ((atom x) ...) (t (assert (consp x)) ...)) covers all the cases. Now, your add-fact is hybrid. In some cases it destructively modifies the database list (setf (rest database) ...) in some other cases, it behaves functionnaly, returning a newly allocated list: (list new-fact) It would be better to be always functionnal, or always procedural. In the first case: (defun add-fact (database new-fact) (if (consp new-fact) (if (null database) (list new-fact) (cons new-fact database)) database)) Then you must use always add-fact as: (setf database (add-fact database new-fact)) In the second case, you cannot do with lists, for lists are either CONS or NIL and NIL is immutable. You have to use a mutable datatype. (defun make-db () (cons :db nil)) (defun dbp (object) (and (consp object) (eq :db (car object)))) (defun add-fact (database new-fact) (when (consp new-fact) (pushnew (cdr database) new-fact)) (values)) The you must use it always as: (add-fact database new-fact) In this second case, such functions are often in COMMON-LISP, prefixed with 'n': nadd-fact in scheme, suffixed with '!': add-fact! to signal they non-functional behavior. > Does anyone have an idea what is going on here? Read again what you wrote in your add-fact. -- __Pascal Bourguignon__ http://www.informatimago.com/ Small brave carnivores Kill pine cones and mosquitoes Fear vacuum cleaner |