24

What does the syntax, colons preceding variable in Common Lisp, mean? I've seen programs with such, and I'll present some sample code here, out of a large set of functions.

(defun expand (successorf node)
    (mapcar (lambda (action-state-cost)
          (let ((action (car action-state-cost))
                (state (cadr action-state-cost))
                (cost (caddr action-state-cost)))
            (make-node :state state :parent node
                       :action action :path-cost (+ (node-path-cost node) cost)
                       :depth (1+ (node-depth node)))
            ))
      (funcall successorf (node-state node))
      ))
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
cyberfrenzy
  • 271
  • 2
  • 6

2 Answers2

39

Keyword Symbols

:foo is a keyword symbol.

  • interned in and exported from the KEYWORD package
  • constantly bound to itself

Usage

Keyword symbols are used when one needs the combination of the following properties:

  • a symbol is the right data structure
  • symbols with the same name should be unique (by interning them in a package) -> package KEYWORD
  • different packages are not needed or wanted -> package KEYWORD
  • writing the symbol should be easy by not needing to quote them -> :foo better than ':foo
  • the ability to act as a variable with different values is not needed -> :foo evaluates to :foo itself and only to :foo

In Common Lisp generally symbols can be in a package (kind of a namespace).

An unexported symbol bar in a package foo is written as foo::bar. The double colon is between the package name and the symbol name.

An exported symbol then is written as foo:bar. A single colon is used.

If the symbol is available in the current package then is written as bar without the package.

The package KEYWORD

There is a special package called KEYWORD. A symbol bar in that package is simply and always written as :bar.

Examples

These keyword symbols have also these interesting properties: the symbols are automatically exported from the package KEYWORD (so keyword::bar, keyword:bar, ::bar and :bar are all the same symbol) and they evaluate to themselves:

CL-USER 5 > :bar
:BAR

CL-USER 6 > (describe :bar)

:BAR is a SYMBOL
NAME          "BAR"
VALUE         :BAR
FUNCTION      #<unbound function>
PLIST         NIL
PACKAGE       #<The KEYWORD package, 0/4 internal, 5830/8192 external>

CL-USER 7 > (eq 'keyword::bar ':bar)
T

CL-USER 8 > (eq :bar ':bar)  ; quoted or unquoted, each subform evaluates to :bar
T

Usage

Keyword symbols are used for example as names in named arguments:

(defun foo (&key bar) (+ bar 10))

(foo :bar 7)

Typically they are also used in arguments to instance and structure construction.

(defstruct node state parent action)

DEFSTRUCT is a Common Lisp macro and it generates several functions. One of them is a function MAKE-NODE, which can be used as:

(make-node :state 'open
           :parent some-parent
           :action an-action)

Note: sometimes the data might also be a keyword. For example in above form, the state might be :open and not open:

(make-node :state :open
           :parent some-parent
           :action an-action)
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
  • You write: "An **exported symbol**... is written as `foo:bar`. *A single colon is used*.." and also "the [keyword] symbols are **automatically exported**," but your example shows `(eq 'keyword::bar ':bar)`. Why do you use the double-colon if keywords are always exported? Can `::` be used with both exported and non-exported symbols? – Glenn Slayden Oct 15 '17 at 18:14
  • @GlennSlayden Yes, every interned symbol, exported or not exported, can be written as package::name . Only exported symbols can be written as package:name . Only keyword symbols can be written as :name . – Rainer Joswig Oct 15 '17 at 18:19
  • For completeness, what about `::bar`? Does it still refer to the `KEYWORD` package, or would that now be some other form of global? Sorry for being a LISP newbie. – Glenn Slayden Oct 15 '17 at 18:28
  • 1
    @GlennSlayden: :bar , ::bar , keyword:bar , keyword::bar are all the same symbol. (mapcar (lambda (sym) (eq sym :bar)) '(:bar ::bar keyword:bar keyword::bar)) -> (T T T T) – Rainer Joswig Oct 15 '17 at 19:57
21

They're not variables, actually; those are keywords. They're a special kind of efficient token, similar to “atoms” in other languages. It's a convenient, built-in way to pass named (and, almost always, optional) parameters into a function call.

http://www.gigamonkeys.com/book/functions.html describes the syntax of function calls.

BRPocock
  • 13,638
  • 3
  • 31
  • 50