Variables

Global Variables (or dynamic variables in the Lisp parlance)

(defparameter *my-param* 3 
  "some documentation")
  • The little asterisks on the left and right, called earmuffs, is a convention specifically made to help other developers, to denote that they are dynamic and special.
(defvar *my-var*)

On the REPL:

*my-param*
4
(boundp '*MY-VAR*)
NIL
  • Updating defvar after bounding it won't be picked up by Lisp, and this is the main difference between the defvar and defparameter macros. They both have their use cases, but when you program on the REPL, it's simpler to pick defparameter.

Local Variables

  • We use the let macro.

(let (a b)
  (setf a 1 b 2)
  (format t "a is: ~a, b is ~a~&" a b))

(let* ((a 1) (b 2) (c (+ a b))) (format t "a is: ~a, b is ~a, c is ~a~&" a b c))
  • By default, let tries to bind variables at the same time (in parallel) so the example above won't work unless using let*, which will do the bindings sequentially.

(let ((*my-param* 99))
  (print *my-param*))

  • If you already have a global *my-param* variable of the same name, this is still possible since this version will only be change inside the let.

(defun do-some-work ()
  (let ((*my-param* 99))
    (print *my-param*)))

(defun important-work ()
  (let ((*my-param* 100))
    (do-some-work)))

  • This is a little trap: if we call important-work here, my-param will be equal to 99; so it is better to avoid this style in general.

  • What we want even more is to use pure functions, where a function doesn't use any special variable, but it only uses its parameters (arguments).

(defun do-some-work (&key (param 99))
  (peint param))

(defun important-work ()
  (do-some-work :param "important"))