Hi,
A way to understand how recursive functions work is to use the 'trace' LISP function and the vlide 'Trace' window.
Try:
(trace AT:ListCondense)
Then run:
(AT:ListCondense '((1 2) (3 (4 5))))
In the vlide 'Trace' window you can see all recursive calls and their results:
Saisie (AT:LISTCONDENSE ((1 2) (3 (4 5))))
Saisie (AT:LISTCONDENSE (1 2))
Saisie (AT:LISTCONDENSE 1)
Résultat: (1)
Saisie (AT:LISTCONDENSE (2))
Saisie (AT:LISTCONDENSE 2)
Résultat: (2)
Saisie (AT:LISTCONDENSE nil)
Résultat: nil
Résultat: (2)
Résultat: (1 2)
Saisie (AT:LISTCONDENSE ((3 (4 5))))
Saisie (AT:LISTCONDENSE (3 (4 5)))
Saisie (AT:LISTCONDENSE 3)
Résultat: (3)
Saisie (AT:LISTCONDENSE ((4 5)))
Saisie (AT:LISTCONDENSE (4 5))
Saisie (AT:LISTCONDENSE 4)
Résultat: (4)
Saisie (AT:LISTCONDENSE (5))
Saisie (AT:LISTCONDENSE 5)
Résultat: (5)
Saisie (AT:LISTCONDENSE nil)
Résultat: nil
Résultat: (5)
Résultat: (4 5)
Saisie (AT:LISTCONDENSE nil)
Résultat: nil
Résultat: (4 5)
Résultat: (3 4 5)
Saisie (AT:LISTCONDENSE nil)
Résultat: nil
Résultat: (3 4 5)
Résultat: (1 2 3 4 5)
Here's another way for the same task.
The code isn't so concise but may run a little faster because of less recursive calls and the use of 'cons' instead of 'append' (which is more expansive).
The main function: gc:flatlist uses an auxiliary recursive function: foo.
foo is 'tail recursive' (AFAIK AutoLISP do not optimize
tail recursion, but many othe functional languages as F# do) and uses an accumilator (acc) to store the result (in reverse order due to the use of cons).
foo requires two arguments: the list to be processed (lst) and the the list to be returned (acc).
The fuction first evaluates if lst is not nil (empty list)
- if so, calls foo passing it the list tail (cdr) as first argument and, for the second argument, evaluates if the list head (car) is an atom or a list.
-- if it's an atom, just had it to the top of the current accumulator
-- if it's a list, calls foo passing it this list and the current accumulator
- if the list is empty, returns the accumultator
gc:flatlist calls foo passing it the list to process and an empty list as accumulator and reverses the returned list.
(defun gc:flatlist (lst / foo)
(defun foo (lst acc)
(if lst
(foo
(cdr lst)
(if (atom (car lst))
(cons (car lst) acc)
(foo (car lst) acc)
)
)
acc
)
)
(reverse (foo lst nil))
)
Tracing the 'foo' subfunction with the same list as upper:
Saisie (FOO ((1 2) (3 (4 5))) nil)
Saisie (FOO (1 2) nil)
Saisie (FOO (2) (1))
Saisie (FOO nil (2 1))
Résultat: (2 1)
Résultat: (2 1)
Résultat: (2 1)
Saisie (FOO ((3 (4 5))) (2 1))
Saisie (FOO (3 (4 5)) (2 1))
Saisie (FOO ((4 5)) (3 2 1))
Saisie (FOO (4 5) (3 2 1))
Saisie (FOO (5) (4 3 2 1))
Saisie (FOO nil (5 4 3 2 1))
Résultat: (5 4 3 2 1)
Résultat: (5 4 3 2 1)
Résultat: (5 4 3 2 1)
Saisie (FOO nil (5 4 3 2 1))
Résultat: (5 4 3 2 1)
Résultat: (5 4 3 2 1)
Résultat: (5 4 3 2 1)
Saisie (FOO nil (5 4 3 2 1))
Résultat: (5 4 3 2 1)
Résultat: (5 4 3 2 1)
Résultat: (5 4 3 2 1)