4.4 The @ Macro

Common Lisp is a "Lisp-2", meaning a two-namespace Lisp in which a given name can have both a function binding and a value binding. In a Lisp-1, like Scheme, it would be nice to set the FSet types up as objects that could be called as functions as well as having the various operations invoked on them (some object systems for other Lisps have supported this, such as that of T). Then, instead of (lookup m x) where m is a map, you could write simply (m x). But this doesn’t work in a Lisp-2, since the car of a form is evaluated in the function namespace; you’d have to write (funcall m x), which isn’t any more elegant.

What I can do, however, is give you a shorter name to type than funcall. Thus is born @. It is a macro that expands to code that tests whether its first argument is a Lisp function; if so, it funcalls it (with the supplied arguments); otherwise it calls lookup on it. So you can use it when writing higher-order code to make it accept a map as well as a unary Lisp function. (Also, a seq behaves as a map from index to element, and a set behaves as a map from value to boolean, and a bag behaves as a map from value to multiplicity.)

Whether you want to use @ generally, in place of lookup, is a matter of taste. Both are setf-able; though doing (setf (@ m x) y) works only if m is an FSet collection. Remember, this doesn’t modify the collection; it’s equivalent to (setf m (with m x y)).

If you use Emacs for editing, you might find that it doesn’t treat @ as a symbol, which can occasionally be annoying. Adding this line to your init file (~/.emacs or ~/.emacs.d/init.el) should cure the problem:

(modify-syntax-entry ? "_" lisp-mode-syntax-table)