So, I am starting this topic regarding research (solving problems) in area of writing short and simple, but useful non command functions that may/colud be used in occasional process of writing more complex and longer code structures regarding solving more difficult programming tasks that may occur if one is interested in using computational power of software that supports usage of AutoLISP programming language (for ex. AutoCAD, BricsCAD, ...) ...
SIMPLE "RECURSION" EXAMPLES BY M.R. involving none, one or more arguments, none, one or more variables, none, one or more helper sub functions :
OPERATING WITH NUMBER(S) :
;;; we start with simple reducing recursion which outputs list of numbers - array generated from starting input positive number grater than 0
(defun f ( n )
(if (> n 0) ;;; main condition and at the same time, terminator of reducing down number recursion
(cons n (f (1- n)))
)
)
;;; evaluation :
: (f 5)
(5 4 3 2 1)
;;; now from 1 to 5 - adding up recursion
1. simple reverse output of reducing recurion described initially; recursive reducing down number function was used as helper function and result is reversed
(defun f ( n / ff )
(defun ff ( k )
(if (> k 0)
(cons k (ff (1- k)))
)
)
(reverse (ff n))
)
;;; evaluation :
: (f 5)
(1 2 3 4 5)
: !ff
nil
2. transforming - operand to + by supplying negative starting number (- n) [in other words (k) looked through helper function] as first argument to similar helper function now with 2 arguments : second argument was added (m); (1- becomes 1+ : [(1- n) becomes (1+ k)]); main condition (> n 0) bocomes opposite (< k 0) - now refering to negative values that are increasing; and with each pass recursion is cons'-ing positive number by addition (1+ n) [in other words (1+ m) looked through helper function]; second argument is just here for confirmation of the same adding value with each pass - its value is n [m through (ff)]
(defun f ( n / ff )
(defun ff ( k m )
(if (< k 0)
(cons (+ 1 m k) (ff (1+ k) m))
)
)
(ff (- n) n)
)
;;; evaluation :
: (f 5)
(1 2 3 4 5)
: !ff
nil
3. helper dummy variable (k) initially set to 1 is used in adding up number recursion that calls itself exactly the same way [(f n)] until main condition { [(< k (1+ n))] involving increasing variable (k) [(1+ k)] and initially called value (n) which always remains the same unchanged } fails, terminating process
(defun f ( n )
(setq k (if k (1+ k) 1))
(if (< k (1+ n))
(cons k (f n))
(setq k nil)
)
)
;;; evaluation :
: (f 5)
(1 2 3 4 5)
: !k
nil
4. helper dummy function with 2 arguments (ff k n) is used, but it's recursing by adding up number - first argument is increasing and second stays the same - comparison value always remains the same
(defun f ( n / ff )
(defun ff ( k n )
(if (< k (1+ n))
(cons k (ff (1+ k) n))
)
)
(ff 1 n)
)
;;; evaluation :
: (f 5)
(1 2 3 4 5)
: !ff
nil
OPERATING WITH LIST(S) :
;;; we start with simple list length reducing recursion which outputs result the same as input
(defun f ( l )
(if l ;;; there is still 1 element present in l [ optional (> (length l) 0) ]
(cons (car l) (f (cdr l))) ;;; (f (cdr l)) - simple list length reducing recursion
)
)
;;; evaluation :
: (f '(a1 a2 a3 a4))
(A1 A2 A3 A4)
;;; now consider this example with just normal recursion - list length stays the same each pass - we only reverse list each time
(defun ff ( l )
(if (> (length l) 1) ;;; there are still 2 elements present in list (l); if list (l) is defined such as (equal l '(a1 a2)), this condition is always T if we don't reduce list length in next statements/expressions that follows (then) condition of (if) function
(cons (car l) (ff (reverse l))) ;;; this recursion will loop endlessly - there is no reducing factor in evaluation of recursion
)
)
;;; so we need condition to terminate ff function ; for ex. this is how it works without terminator :
;;; if (equal l '(a1)) , when starting (ff l) , in processing return would be nil as initial condition (> (length '(a1)) 1) is not true, so nil would be printed as result and return of evaluation can be passed in meaningful form...
;;; if (equal l '(a1 a2)) , when starting (ff l) , in processing return would be '(a1 a2 a1 a2 a1 a2 ... ) without termination - nothing would be printed as result and return of evaluation couldn't be passed in meaningful form...
;;; if (equal l '(a1 a2 a3)) , when starting (ff l) , in processing return would be '(a1 a3 a1 a3 a1 a3 ... ) without termination - nothing would be printed as result and return of evaluation couldn't be passed in meaningful form...
;;; evaluation (output in BricsCAD) :
; error : LISP - lisp recursion stack limit exceeded
;;; lets try to implement termination condition
(defun ff ( l )
(if
(and
(> (length l) 1) ;;; first condition from previous example (this is used as terminator in reducing recursion when main list length is lesser with each pass - something like : (ff (cdr l)), or (ff (cddr l)), or (ff (vl-remove [(car l)/(last l)] l)) - note here that if l had multiple [(car l)/(last l)] occurences, all of them would be trimmed in next pass, or more strict - removing duplicates not allowed (ff (butlast l)), where (defun butlast ( l ) (reverse (cdr (reverse l))) )
(< (setq n (if n (1+ n) 1)) 4) ;;; termination condition (this is used in building - cons'ing recursion)
)
(cons (car l) (ff (reverse l)))
(setq n nil)
)
)
;;; if (equal l '(a1)) , when starting (ff l) , in processing return would be nil as initial condition (> (length '(a1)) 1) is not true, so nil would be printed as result and return of evaluation can be passed in meaningful form...
;;; if (equal l '(a1 a2)) , when starting (ff l) , in processing return would be (a1 a2 a1), but some processing happened : '(a1) - first pass, '(a1 a2) - second pass, '(a1 a2 a1) - third pass, and when reaching '(a1 a2 a1 a2) , termination condition (< (setq n (if n (1+ n) 1)) 4) would not be true, so (a1 a2 a1) would be printed as result and return of evaluation can be passed in meaningful form...
;;; if (equal l '(a1 a2 a3)) , when starting (ff l) , in processing return would be nil, but some processing happened : '(a1) - first pass, '(a1 a3) - second pass, '(a1 a3 a1) - third pass, and when reaching '(a1 a3 a1 a3) , termination condition (< (setq n (if n (1+ n) 1)) 4) would not be true, so (a1 a3 a1) would be printed as result and return of evaluation can be passed in meaningful form...
;;; if (equal l '(a1 a2 a3 a4)) , when starting (ff l) , in processing return would be nil, but some processing happened : '(a1) - first pass, '(a1 a4) - second pass, '(a1 a4 a1) - third pass, and when reaching '(a1 a4 a1 a4) , termination condition (< (setq n (if n (1+ n) 1)) 4) would not be true, so (a1 a4 a1) would be printed as result and return of evaluation can be passed in meaningful form...
;;; now lets try something different (to achieve different result) - we will use SHIFTING procedure instead of sucessive REVESING of list while recursion processes
;;; technique : just replace [ (reverse l) ] with [ (append (cdr l) (list (car l))) ] - normal shifting; [ (append (cddr l) (list (car l) (cadr l))) ] - shifting by 2 elements; generaly SHIFTING : (defun shift ( l n ) (repeat n (setq l (append (cdr l) (list (car l))))) ) / or in opposite direction : (defun shift ( l n ) (repeat n (setq l (cons (last l) (butlast l)))) ) : usage (shift l 3)
(defun ff ( l )
(if
(and
(> (length l) 1) ;;; first condition from previous example (this is used as terminator in reducing recursion when main list length is lesser with each pass - something like : (ff (cdr l)), or (ff (cddr l)), or (ff (vl-remove [(car l)/(last l)] l)) - note here that if l had multiple [(car l)/(last l)] occurences, all of them would be trimmed in next pass
(< (setq n (if n (1+ n) 1)) 4) ;;; termination condition (this is used in building - cons'ing recursion)
)
(cons (car l) (ff (append (cdr l) (list (car l)))))
(setq n nil)
)
)
;;; if (equal l '(a1)) , when starting (ff l) , in processing return would be nil as initial condition (> (length '(a1)) 1) is not true, so nil would be printed as result and return of evaluation can be passed in meaningful form...
;;; if (equal l '(a1 a2)) , when starting (ff l) , in processing return would be (a1 a2 a1), but some processing happened : '(a1) - first pass, '(a1 a2) - second pass, '(a1 a2 a1) - third pass, and when reaching '(a1 a2 a1 a2) , termination condition (< (setq n (if n (1+ n) 1)) 4) would not be true, so (a1 a2 a1) would be printed as result and return of evaluation can be passed in meaningful form...
;;; if (equal l '(a1 a2 a3)) , when starting (ff l) , in processing return would be (a1 a2 a3), as some processing happened : '(a1) - first pass, '(a1 a2) - second pass, '(a1 a2 a3) - third pass, and when reaching '(a1 a2 a3 a1) , termination condition (< (setq n (if n (1+ n) 1)) 4) would not be true, so (a1 a2 a3) would be printed as result and return of evaluation can be passed in meaningful form...
;;; if (equal l '(a1 a2 a3 a4)) , when starting (ff l) , in processing return would be (a1 a2 a3), as some processing happened : '(a1) - first pass, '(a1 a2) - second pass, '(a1 a2 a3) - third pass, and when reaching '(a1 a2 a3 a4) , termination condition (< (setq n (if n (1+ n) 1)) 4) would not be true, so (a1 a2 a3s) would be printed as result and return of evaluation can be passed in meaningful form...
;;; now lets add more obvious scheme for recursion that combines building cons'ing result and at the same time operates with list in background that is used for aquireing data ; we are now using 2 arguments - to avoid possible needness for localizing and nil-ing normal variables that could be used inside function upon processed execution (arguments always have better practical usage than variables - [arguments - they serve for passing data to the function that is called with passing values at explicite position of corresponding arguments array definition in reference function; variables - they serve for passing data to specified symbol inside reference function (they can built expressions that function uses to return resulting value upon execution))
(defun ff ( l r )
(if
(and
(> (length l) 1) ;;; first condition - in case we are reducing list length through processing...
(< (length r) 4) ;;; second condition - terminator - it is now referenced on list length of resulting output
)
(progn
(setq r (cons (car l) r)) ;;; cons-ing - building result with data from helper list
(ff (reverse l) r) ;;; recursing with changed helper list and specified 2nd argument for correct recurse call
)
(reverse r) ;;; if conditions aren't met - output resulting list in correct array by reversing built variable... Note : here "r" variable was used in (setq)-ing and buiding list, but as name of variable and initial 2nd argument of (ff) function is the same - there is no need for nil-ing it at the end : every argument of function is evaluated upon execution as nil, despite result-ing output which has valuable data
)
)
;;; evaluation - (you must supply starting value of argument "r" for resulting list as : "nil" - empty starting list) :
: (ff '(a1) nil)
nil
: !r
nil
: (ff '(a1 a2) nil)
(A1 A2 A1 A2)
: !r
nil
: (ff '(a1 a2 a3) nil)
(A1 A3 A1 A3)
: !r
nil
: (ff '(a1 a2 a3 a4) nil)
(A1 A4 A1 A4)
: !r
nil
: (ff '(a1 a2 a3 a4 a5) nil)
(A1 A5 A1 A5)
: !r
nil
;;; now lets do it more suitable in terms of input/output relations (one list - input; one list - output) :
(defun ff ( l / fff )
(defun fff ( ll r )
(if (and (> (length ll) 1) (< (length r) 4)) ;;; this second expression of (and) function [(< (length r) 4)] could be replaced with maybe more suitable expression [(< (length r) (length ll))] involving comparison of lengths of resulting list and initial list - termination occurs when resulting list length matches initial input list length
(progn (setq r (cons (car ll) r)) (fff (reverse ll) r))
(reverse r)
)
)
(fff l nil)
)
;;; evaluation :
: (ff '(a1 a2 a3 a4 a5))
(A1 A5 A1 A5)
: !fff
nil
SIMPLE "NON RECURSION" EXAMPLES BY M.R. involving none, one or more arguments, none, one or more variables, none, one or more helper sub functions :
;;; here is the most basic one with building list of numbers in ascending order from 1 upwards :
(defun f ( n / k r )
(repeat n
(setq r (cons (setq k (if k (1+ k) 1)) r))
)
(reverse r)
)
;;; evaluation :
: (f 5)
(1 2 3 4 5)
: !k
nil
: !r
nil
NOW, YOU MAY CONTINUE WITH YOUR : STUDY EXAMPLES / QUESTIONS / SOLUTIONS / PROBLEMS-TASKS TO BE SOLVED / OPINIONS / COMMENTS / SUGGESTIONS / LINKS (FOR REVISION) / ADVICES ... (AND SO ON, SO ON ...)
IT BEGINS WITH SIMPLE EXAMPLES, BUT TOPIC SHOULD CONTINUE TO GROW - IT SHOULD INCREASE RESEARCH DIFFICULTY ASPECTS IN ALL SPHERES : PROVIDED APPROACHES TO SPECIFIC PROBLEMS, PROVIDED EXAMPLES/SOLUTIONS, PROVIDED NOT SOLVED PROBLEMS/DIFFICULTIES THAT PROVED TO BE IMPORTANT/RELEVANT TASKS TO BE APPLIED IN PROGRAMMING/STUDIED IN THE FUTURE...