Почему двоеточие предшествует переменным в 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)