views:

175

answers:

3

I wonder why in the following code, d is not being consed into x. Any hints are much appreciated.

(defun it (x) 
  (setq f '(a b c))
  (dolist (d f)
    (cons d x))
  (print x))

Thank you!

+9  A: 

I don't know a lot about LISP, but here's a few things I think I know that might help you:

  • (cons d x) doesn't put d "into" x; it creates a new value that consists of d, followed by the contents of x. If x is a list, then (cons d x) will also be a list.

  • (cons d x) doesn't change anything; it creates a value, but if you don't capture that value, it gets discarded again. In particular, that expression doesn't change x.

Carl Smotricz
cons does NOT create a new list. It just creates a new cons cell (a structure with two pointers and returns that. The CAR of that cell is the first argument of CONS and the CDR of that cell is the second argument of CONS.
Rainer Joswig
I knew that, but I was hoping to keep it simple. Still, you're right that I shouldn't let the lie stand there. I'll edit my post.
Carl Smotricz
A: 

If I understand your intention properly, you want to append the list f comprising the symbols a, b, and c to the supplied argument x. How about this?

 (defun it (x)
   (append (if (listp x)
               x
               (list x))
           '(a b c)))

Note that cons doesn't modify any existing structures; it means "construct", and it creates fresh structure. In this case, you don't need to modify any anything, unless you're deliberately trying to write a destructive function that would modify the object pointed to by argument x in place. Such functions are rare and are usually named in a way to warn of such destructive behavior, such as nconc or nreverse. The leading n means "non-consing", suggesting it modifies existing structure rather than creating fresh structure.

seh
+6  A: 

You need to use PUSH to update a variable destructively. CONS just returns a new cons cell. If you don't do anything with that cons cell, then it is gone. Also not that you need to declare all variables. LET introduces a new local variable F, so LET is useful in your example. Just doing SETQ or SETF on an undeclared variable is not a good thing to do - actually in the Lisp standard, the consequences are undefined for such an operation.

(defun it (x) 
  (let ((f '(a b c)))
    (dolist (d f)
      (push d x))
    (print x)))

Or use a more functional approach.

(defun it (x)
  (print (append '(a b c) x)))

You also might want to throw in a call to REVERSE to get a different order of list elements.

Rainer Joswig