Skip to content

LISP - Calling Function using funcall

Lisp - Dynamic Function Calls with funcall

Section titled “Lisp - Dynamic Function Calls with funcall”

In Common Lisp, functions are first-class citizens. This means they can be stored in variables, passed as arguments to other functions, and returned as results. The funcall function is a fundamental tool that allows you to invoke a function object that you have at runtime. This is essential for writing higher-order functions and implementing dynamic behavior.

(funcall function-designator arg1 arg2 ...)

Where:

  • function-designator: This is the function to be called. It can be a symbol that names a function (e.g., '+, 'my-function), a lambda expression (an anonymous function), or a function object itself.
  • arg1, arg2, …: These are the arguments to be passed to the specified function.

Pro-Tip: To get a function object from a name, use the special function operator, or its reader macro shorthand #'. For example, (function +) is the same as #'+.

You can use a symbol to dynamically call a function by its name.

;;; Define a simple function
(defun multiply-by-two (x)
(* x 2))
;; Call a built-in function using its symbol name
(print (funcall '+ 2 3))
;; Call our custom function using its symbol name
(print (funcall 'multiply-by-two 5))

Executing the code produces the following result:

5
10

Example 2: Using a Variable to Hold a Function

Section titled “Example 2: Using a Variable to Hold a Function”

This demonstrates the power of first-class functions, where the operation to be performed can be decided at runtime.

(defun multiply-by-two (x) (* x 2))
(defun add-ten (x) (+ x 10))
;; Use LET to bind a function object to a local variable
(let ((operation #'*))
(print (funcall operation 4 5))) ; Evaluates to 20
(let ((operation #'add-ten))
(print (funcall operation 6))) ; Evaluates to 16
20
16

funcall can directly invoke an anonymous function created with lambda.

;; Call a lambda expression that multiplies two numbers
(print (funcall #'(lambda (x y) (* x y)) 3 4))
12

Example 4: Creating a Higher-Order Function

Section titled “Example 4: Creating a Higher-Order Function”

A higher-order function is a function that takes another function as an argument. funcall makes this easy to implement.

;; Define a higher-order function that applies an operation to two arguments
(defun apply-operation (operation arg1 arg2)
(funcall operation arg1 arg2))
;; Use the higher-order function with different operations
(print (apply-operation #'+ 10 5))
(print (apply-operation #'* 10 5))
(print (apply-operation #'(lambda (a b) (- a b)) 10 5))
15
50
5

A common error is trying to funcall a symbol that is not defined as a function. The Lisp system will signal an undefined-function error.

Also, be aware of the apply function. It is similar to funcall, but its last argument must be a list of arguments for the function being called.

(funcall #'+ 1 2 3) ; Passes 1, 2, 3 as three separate arguments
(apply #'+ '(1 2 3)) ; Passes the elements of the list (1 2 3) as arguments
(apply #'+ 1 2 '(3 4)) ; `apply` can also take leading arguments
  • Dynamic Dispatch: funcall is the primary mechanism for invoking a function when the specific function is not known until runtime.
  • First-Class Functions: funcall fully embraces Lisp’s treatment of functions as data, enabling powerful functional programming patterns.
  • Higher-Order Functions: It is the key to creating functions that accept other functions as arguments, a cornerstone of modern software design.