Adam S
Adam S

Reputation: 9255

Calling functions by name at runtime

I realize that a function can be referenced using #'PRINT to reference the PRINT function. If we have a list S where the first element is 'PRINT , can we reference this using #(car S) ?

Say I'm looking at a list where the elements in the list are atoms which are the names of some functions. Currently, I can do this:

(defun aritheval (S)
    (funcall
        (cond
            ((eq '+ (car S)) #'+)
            ((eq '- (car S)) #'-)
            ((eq '* (car S)) #'*)
            ((eq '/ (car S)) #'/)
        )
        '2
        '3
    )
)

This function would compute 2+3, 2-3, 2*3 or 2/3 depending on the first element in list S. S contains the names of these functions.

Upvotes: 1

Views: 139

Answers (1)

Rainer Joswig
Rainer Joswig

Reputation: 139411

#(car S) makes no sense. The syntax exists but means a vector with symbols CAR and S.

use

(funcall (first somelist) someargument)

or

(apply (first somelist) a-list-of-arguments)

Your function is non-Lispy formatted.

Trailing parentheses are not used in proper Lisp code. You also don't need to quote numbers. Numbers are self-evaluating, they evaluate to themselves. Also we now may prefer FIRST over CAR and REST over CDR. The functions do the same, but the names are better. Whenever we deal with simple lists, FIRST, SECOND, THIRD, ... and REST are used.

(defun aritheval (S)
  (funcall (cond ((eq '+ (car S)) #'+)
                 ((eq '- (car S)) #'-)
                 ((eq '* (car S)) #'*)
                 ((eq '/ (car S)) #'/))
            2 3)))

Since symbols can be used as names for global functions, above is not necessary.

This function below does the same, given the mapping from symbol to function is the same.

(defun aritheval (s)
  (funcall (first s) 2 3)))

Upvotes: 6

Related Questions