7

I have some basic questions about elisp.

I often see something like

(search-forward "something" nil 'noerror)

And sometimes I see something like

(search-forward "something" nil :noerror)

What is the difference and should I prefer one form over the other?

As far as I understand everything but the empty list evaluates to true in a boolean context. But how comes the following:

When the searchterm "something" does not exist in the buffer the point jumps to the end of the buffer when 'noerror is used instead of t. When t is used the point stays where it is.

First case:

(search-forward "something" nil 'noerror);; 1.Evaluate this

;; end of buffer 2.point jumps here

Second case:

(search-forward "something" nil t);; 1.Evaluate this, 2. Point stays here

;; end of buffer
  • 1
    FWIW: When all non-nil values are treated the same by the given function, in my code I pass a symbol with the same name or similar to the parameter name used in the function description, and typically uppercase. This serves as a reminder to me, when I read the code. E.g. (search-forward "abc" nil 'NOERROR). It is most helpful for optional arguments that are seldom used. – Drew Oct 3 '15 at 15:55
12

Boolean values in elisp work as follows:

  • nil and () (which, as you've observed, are the same thing) are false
  • Absolutely anything else is true.

The t symbol exists as a 'pure' value of true (when there's no benefit to using another value), but most functions will try to return something which might be otherwise useful, whenever possible.

See also C-hig (elisp) nil and t RET

When it comes to using keyword arguments or other symbols as a non-nil value when the code only cares about nil or non-nil, it's really just a matter of personal preference. There's no difference in terms of execution.

I once asked the same thing, and was informed that the keyword argument approach is a more Common Lisp-ish method.

(I've settled on using keyword arguments myself, partly for the syntax highlighting, and partly because it better differentiates them from variable and function symbols.)

Regarding your specific example, the function does differentiate between various non-nil values, and that behaviour is covered by its docstring:

Optional third argument, if t, means if fail just return nil (no error). If not nil and not t, move to limit of search and return nil.

In general you'll notice that docstrings tend to refer to "non-nil" rather than "true" or "t". If you do see "t" then there's a fair chance that it's a special case.

  • Thanks, that clarified it for me! So everything but nil is true but t as "pure" is different from that. – clemera Oct 3 '15 at 14:30
  • 2
    Well, it's still just a symbol (albeit a self-quoting one, like nil is). By "pure" I just mean that it exists specifically to be a value which means "true", because sometimes that's what you want. Other non-nil values are still every bit as "true" as t is, though. – phils Oct 3 '15 at 14:40
14

Some historical reference is due.

Emacs Lisp borrows many things from Common Lisp, but the similarity is only surface deep. Colon symbol in Common Lisp is a namespace qualifier. Canonical symbol names have two parts: the name of the package and the name of the symbol in that package, so, for example, cl-user:apropos is a symbol defined in package cl-user. There is also a special keyword package automatically imported by Common Lisp when it is started. This package is used to communicate between other packages (so that if packages need to send symbolical information to each other, they wouldn't fight over who has to declare it). As you might have guessed, symbols in that package are written with the leading colon.

Emacs Lisp doesn't have a concept of packages, but the colon is still special in that it instructs the reader to interpret the expression as self-evaluating symbol (i.e. it is a variable whose value is that variable itself). There are several such built-in self-evaluating symbols: t and nil are examples I'll write about later.

The apostrophe is also borrowed from Common Lisp, where it is a standard reader macro (i.e. it is a code that the Lisp interpreter executes while reading in the source of the program). It expands as follows: 'x -> (quote x), where (quote ...) is a special form which prevents the Lisp interpreter from evaluating the contents of the expression inside. Emacs Lisp has three built-in reader macros: ', ` and #, but you cannot add your own. First two expand to (quote ...), however the second allows special syntax for building the unevaluated expression. # expands to (function ...) form, which instructs the interpreter that the value must be looked up in the function namespace.

Symbols in Emacs Lisp must evaluate to some value (similar to variables in other languages) otherwise it is an error. However, you may prevent evaluation by using the quote form.

Finally, the difference between:

(search-forward "something" nil 'noerror)

and

(search-forward "something" nil :noerror)

Is that in the first case you called search-forward with a symbol with no value, for which only the name is known, and in the second case you've called this function with a symbol whose value is this symbol itself. It so happens that this function doesn't care about which one you use.


Types are an important programming tool for automatic verification of programs. Emacs Lisp type system is similar to Common Lisp in that its universal type (written as t) is the type from which all other types are derived. On the other hand, nil is the type from which no type is derived (the complement of t). This is unlike many popular programming languages, which may not have a concept of universal type, or have a distinct Boolean type.

Yet again, unfortunately, Emacs Lisp didn't copy this part precisely from Common Lisp, and the type-of function gives confusing results for t and nil.

Emacs Lisp:

(type-of t) ; symbol

Common Lisp

(type-of t) ; BOOLEAN

Common Lisp extension of Emacs Lisp has a function cl-typep which might, however, help understand the relationship. So, for example

(cl-typep 'noerror t) ; t

i.e. whatever 'noerror is it is of type t.

  • Interesting additional background information, thanks! – clemera Oct 3 '15 at 16:14
  • Wonderful explanation. I learned something about Common Lisp too. Thanks. – gsl Oct 4 '15 at 6:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.