Search code examples
lispautocadautolisp

Lisp - How to call a function within another function?


I am trying to call the following function:

(defun c:Add ()
    (setq a (getint "Enter a number to add 2 to it"))
    (setq a (+ a 2))
)

Inside this LOOPER function:

(defun LOOPER (func)
    ;repeats 'func' until user enters 'no'
    (setq dummy "w")
    (while dummy
        (func) ;this is obviously the problem
        (setq order (getstring "\nContinue? (Y or N):"))
        (if (or (= order "N") (= order "n")) (setq dummy nil))
    )
)   

Like this:

(defun c:Adder ()
    (LOOPER (c:Add))
)

How do I get around the fact that func is undefined in LOOPER function?


Solution

  • You can pass a function as an argument to another function as demonstrated by the following example:

    (defun c:add ( / a )
        (if (setq a (getint "\nEnter a number to add 2 to it: "))
            (+ a 2)
        )
    )
    
    (defun looper ( func )
        (while
            (progn
                (initget "Y N")
                (/= "N" (getkword "\nContinue? [Y/N] <Y>: "))
            )
            (func)
        )
    )
    
    (defun c:adder ( )
        (looper c:add)
    )
    

    Here, the symbol c:add is evaluated to yield the pointer to the function definition, which is then bound to the symbol func within the scope of the looper function. As such, within the scope of the looper function, the symbols func and c:add evaluate the same function.

    Alternatively, you can pass the symbol c:add as a quoted symbol, in which case, the value of the symbol func is the symbol c:add which may then be evaluated to yield the function:

    (defun c:add ( / a )
        (if (setq a (getint "\nEnter a number to add 2 to it: "))
            (+ a 2)
        )
    )
    
    (defun looper ( func )
        (while
            (progn
                (initget "Y N")
                (/= "N" (getkword "\nContinue? [Y/N] <Y>: "))
            )
            ((eval func))
        )
    )
    
    (defun c:adder ( )
        (looper 'c:add)
    )
    

    Passing a quoted symbol as a functional argument is more consistent with standard AutoLISP functions, such as mapcar, apply etc.