Почему двоеточие предшествует переменным в Common Lisp
Что означает синтаксис, двоеточие, предшествующее переменной в Common Lisp, означает? Я видел программы с такими, и я приведу здесь пример кода из большого набора функций.
(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))
))
Ответы
Ответ 1
На самом деле они не переменные; это ключевые слова. Они представляют собой особый вид эффективного токена, аналогичного "атомам" на других языках. Это удобный, встроенный способ передачи названных (и, почти всегда, необязательных) параметров в вызов функции.
http://www.gigamonkeys.com/book/functions.html описывает синтаксис вызовов функций.
Ответ 2
Символы ключевых слов
:foo
является символом keyword.
- интернирован и экспортирован из пакета
KEYWORD
- постоянно привязан к себе
Использование
Символы ключевого слова используются, когда требуется сочетание следующих свойств:
- символ - это правильная структура данных.
- символы с тем же именем должны быть уникальными (путем их интернирования в пакете) → package
KEYWORD
- разные пакеты не нужны или не нужны → пакет
KEYWORD
- запись символа должна быть простой, не требуя процитировать их →
:foo
лучше, чем ':foo
- способность действовать как переменная с разными значениями не требуется →
:foo
оценивает только :foo
и только :foo
В Common Lisp обычно символы могут быть в пакете (вид пространства имен).
Необязательный символ bar
в пакете foo
записывается как foo::bar
. Двойной двоеточие находится между именем пакета и именем символа.
Затем экспортированный символ записывается как foo:bar
. Используется один двоеточие.
Если символ доступен в текущем пакете, он записывается как bar
без пакета.
Пакет KEYWORD
Существует специальный пакет под названием KEYWORD
. Символ bar
в этом пакете просто и всегда записывается как :bar
.
<сильные > Примеры
Эти ключевые слова имеют также эти интересные свойства: символы автоматически экспортируются из пакета KEYWORD
(поэтому keyword::bar
, keyword:bar
, ::bar
и :bar
- все те же символы), и они оценивают сами по себе:
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
Использование
Символы ключевых слов используются, например, как имена в именованных аргументах:
(defun foo (&key bar) (+ bar 10))
(foo :bar 7)
Обычно они также используются в аргументах для построения экземпляра и структуры.
(defstruct node state parent action)
DEFSTRUCT
является общим макросом Lisp, и он генерирует несколько функций. Одна из них - это функция MAKE-NODE
, которая может использоваться как:
(make-node :state 'open
:parent some-parent
:action an-action)
Примечание: иногда данные также могут быть ключевым словом. Например, в приведенной выше форме состояние может быть :open
, а не open
:
(make-node :state :open
:parent some-parent
:action an-action)