Congratulations on making it print a nested list, a further step than what I had suggested. Complete this, and you will know recursion better than most working programmers.
Below is the code I typed this morning, which also has space formating errors, and also is probably not the best way to do recursion. Despite that, it also prints a nested list, which perhaps is testament to the flexible quick codability of lisp. It's probably not the best way to do recursion because of the &optional switch it uses to print the first "[" character.
Code: Select all
(defun e(x &optional y)
(if (not (eq y 1)) (princ "["))
(if (eq nil x) (progn (format t " ]") nil)
(progn (if (atom x) (format t " ~a" x)
(progn
(if (listp (car x)) (format t " ["))
(e (car x ) 1)
(e (cdr x ) 1))))))
The code you have so far has an additional error of not printing an empty list:
CL-USER> (show-list '(1 2 3))
[1 2 3 ]NIL
CL-USER> (show-list '(1 2 (4) 3))
[1 2 [4 ]3 ]NIL
CL-USER> (show-list '(1 2 () 3))
[1 2 ]3 ]NIL
It's doing that because instead of testing if the car of x is a list and printing "[" based on that, your code is using mapcar to print "[" in front of all none empty list cars by default. If () and null were not the same thing in lisp, this wouldn't have caused that particular error, but probably a different one. This shows the dangers and extra complexity of using mapcar in recursion, instead of final base case testing.
pg explains in 'ansi lisp' that recursion is great for saving time in making loop control code, and the way to do that is to determine the none final base cases and the final base cases. The final base cases is/are where the recursion should 'hit bottom.' The none final base cases is/are where it's still recursing. The reason my code uses an &optional switch and has space formatting errors is because I didn't take the time to list and figure out how to code all my base cases. Doing that will produce optimally elegant code.
How many different types of data pieces and situations of encounter will the code have to deal with when recursing? What should be the code for doing that? How many did I include in my code and which did I leave out? How is the logic badly ordered and how can it be improved on with correct base case usage? Which final base case am I overlooking with the &optional switch hack? (hack in the bad sense)
Here is the output from my code:
CL-USER> (e '(1 2 3))
[ 1 2 3 ]NIL
CL-USER> (e '(1 2 (4) 3))
[ 1 2 [ 4 ] 3 ]NIL
CL-USER> (e '(1 2 () 3))
[ 1 2 [ ] 3 ]NIL
ps-maybe one type of switch or another, or multiple defuns, is needed for the first "[", anybody?