There is a problem with your code. You can't used defun inside a function. In your case, the function "helper" defined is global, not local to "cartesian-product". Instead, you should use flet or labels (use labels if the function is going to be recursive).
Also, local variables
must be declared. Again, the variables "k" and "j" in your code are global (or might not even be created). You should declare variables with let or let*.
You are iterating over a list like you would iterate over an array. Don't do this, lists are accessed sequentially, not by index. Instead of "dotimes" and "nth", use "dolist". You don't need neither of the variables j nor k for that matter.
Finally, instead of "cons" inside "cons", there is "list".
This is how your code looks like after those changes:
Code: Select all
(defun cartesian-product (m n)
(flet ((helper (x)
(dolist (j n)
(print (list x j)))))
(mapcar #'helper m)))
This function does what yours does.
Now, instead of printing, how about pushing the elements into a new list?
Code: Select all
(defun cartesian-product (m n)
(let ((new-list nil)) ; nil is the empty list
(flet ((helper (x)
(dolist (j n)
(push (list x j)
new-list))))
(mapcar #'helper m))
;; Needs to return the new-list at the end!!!
new-list))
Please note that, when you use "append" and other functions that operate on lists, they
do not update the value of their arguments! Instead, they return the new list, so you need to fetch the value returned somewhere (into a new variable, as returned-value or to a function call).
"Push" is an exception that updates its second argument because it is not a function, it's a macro that is equivalent to. Only macros (like "setf") can do that. This is what "push" does:
Code: Select all
(push element list) === (setf list (cons element list))
Lisp is this: functions computing and returning values (functional paradigm), not functions doing stuff and changing the values of the variables (imperative paradigm). Of course Lisp has a bit of both paradigms (and others as well), but each paradigm has its place, and imperative don't take place at simple operations on lists.