emacs lisp and static variable

This post is part of the Living with Emacs Lisp series and is about the following question.

How does one emulate static variables (as in C), in elisp?

1. for a toggle function

If the reason you want something like a static variable is for a toggle command that turns something on and off, then you might want to look into defining a minor mode using define-minor-mode.

2. simply using global variables

Alternatively, you can just use a global variable of the same name as the function. In fact, this is how define-minor-mode does it.

As an example, we define a Fibonacci number generator.

(defvar my-fibo-gen (cons 0 1))
(defun my-fibo-gen ()
  (cl-psetf (car my-fibo-gen) (cdr my-fibo-gen)
            (cdr my-fibo-gen) (+ (car my-fibo-gen)
                                 (cdr my-fibo-gen)))
  (car my-fibo-gen))

(my-fibo-gen) ; ⇒ 1
(my-fibo-gen) ; ⇒ 1
(my-fibo-gen) ; ⇒ 2
(my-fibo-gen) ; ⇒ 3
(my-fibo-gen) ; ⇒ 5
(my-fibo-gen) ; ⇒ 8

It can also be OK to use more than one global variables. For example, buffer-face-mode uses two: buffer-face-mode and buffer-face-mode-face.

3. let over lambda

If you enable lexical scope first, then you can use let over lambda like so.

(let ((aa 0)
      (bb 1))
  (defun my-fibo-gen ()
    (cl-psetf aa bb
              bb (+ aa bb))
    aa))

(my-fibo-gen) ; ⇒ 1
(my-fibo-gen) ; ⇒ 1
(my-fibo-gen) ; ⇒ 2
(my-fibo-gen) ; ⇒ 3
(my-fibo-gen) ; ⇒ 5
(my-fibo-gen) ; ⇒ 8

4. optional reading

4.1. symbol properties

Alternatively, some people use symbol properties (of the symbol for the function name) instead. One such example is the function cycle-font in in this link. If you are worried about possible name clash from using simple names for symbol properties, you can put some prefix to the names.

This entry was posted in Emacs, Lisp. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s