Когда ключевые слова clojure должны находиться в пространствах имен? - PullRequest
31 голосов
/ 20 марта 2010

В ближайшем будущем ключевые слова оценивают сами, например ::1001

>>:test
:test

Они не принимают никаких параметров и не связаны ни с чем. Тогда зачем нам нужно определять ключевые слова в пространстве имен?

Я знаю, что для создания isa иерархий с использованием derive требуются ключевые слова с указанием пространства имен (например, ::test). Есть ли другие случаи, когда ключевые слова должны находиться в пространстве имен?

Ответы [ 2 ]

24 голосов
/ 20 марта 2010

Вам следует указывать ключевые слова в пространстве имен, если какой-либо код когда-либо будет иметь возможность взаимодействовать с вашими ключевыми словами вне контекста пространства имен. Основной пример, который я могу вспомнить, - это два пространства имен, помещающие ключи и значения в хэш-карту в третьем пространстве имен, где ключи являются ключевыми словами (как это часто бывает в Clojure). Придуманный пример:

user> (ns main)
nil
main> (def DATA (ref {}))
#'main/DATA
main> (ns foo)
nil
foo> (dosync (alter main/DATA assoc :bad 123 ::good 123))
{:foo/good 123, :bad 123}
foo> main/DATA
#<Ref@541b02: {:foo/good 123, :bad 123}>
foo> (ns bar)
nil
bar> (dosync (alter main/DATA assoc :bad 456 ::good 456))
{:bar/good 456, :foo/good 123, :bad 456}  ;; oops, no more :bad from foo

Почему вы хотите это сделать? Ну, некоторые основные концепции в Clojure (например, derive) реализованы таким образом, как хэш-карты в clojure.core. Мультиметоды также часто распределяют значения ключевых слов, и для пространства имен нередко определяется метод для мультиметода в другом пространстве имен. Нетрудно придумать ситуации, когда автору библиотеки может быть необходим подобный механизм.

Хорошая идея - квалифицировать ваши ключевые слова по пространствам имен, если есть какой-либо риск того, что ваши ключевые слова будут выходить из вашего пространства имен, если только вы не хотите, чтобы ваши ключевые слова перекрывали их из других пространств имен.

11 голосов
/ 20 марта 2010

Единственное место, где Clojure в настоящее время требуется ключевые слова, соответствующие пространству имен, - это использование функции функции extend для добавления реализации протокола к существующему типу. (Это функциональность 1.2, доступная с последними снимками, но не стабильная версия 1.1.) Соответствующий фрагмент из (doc extend):

extension принимает тип / класс (или интерфейс, см. Ниже) и один или несколько протокол + метод карты пар. Это расширит полиморфизм методы протокола для вызова предоставленных методов, когда AType предоставляется в качестве первого аргумента. Обратите внимание, что определены типы типов используя их ключевые слова теги:

:: MyType или: my.ns / MyType

Действительно, для типа Apple и протокола Eatable:

(deftype Apple [colour])
(defprotocol Eatable (eat [x]))

следующее выдает исключение (No implementation of method: :eat и т. Д.):

(extend :Apple Eatable {:eat (fn [x] (println (str (name (:colour x)) ", yummy!")))})
(eat (Apple :red))

пока печатается red, yummy!:

(extend ::Apple Eatable {:eat (fn [x] (println (str (name (:colour x)) ", yummy!")))})
(eat (Apple :red))

Примечание. Я только что набрал все это в REPL. Также обратите внимание, что если вы хотите воспроизвести его, лучше всего набрать / вставить его в порядке, указанном выше; например Переоценка любой из форм (deftype Apple [colour]) и (defprotocol Eatable (eat [x])) (или даже обеих) не заставит Clojure забыть о реализации протокола.

Опять же, это функция 1.2, поэтому она даже отсутствует в 1.1 и может измениться до фактического выпуска 1.2.


Совместное использование хэш-карты между несколькими пространствами имен - еще один возможный вариант использования, как говорит Брайан. Обратите внимание, что нет необходимости задействовать ссылочный тип. Скажем, есть куча библиотек - которые, возможно, будут добавлены в будущем, - которые манипулируют (возможно, трансформируют, может быть, просто наблюдают) хеш-картами с ключевыми словами, где каждая библиотека может свободно определять, какие ключевые слова она ищет и что он использует их для; тогда можно было бы использовать соблюдаемые ключевые слова в пространстве имен, чтобы избежать коллизий.

На самом деле, в настоящее время существует пример, который совсем не надуман, а именно, спецификация Ring v0.1 (ключевой элемент современной экосистемы Clojure Web). См. сообщение для ключевого слова карты запросов и ответов для группы Google Ring (сделано автором Ring
). Mark McGranaghan) для некоторого понимания обоснования этого проектного решения, а также решения больше не требовать ключевых слов пространства имен в спецификации Ring v0.2. Есть также сообщение Джеймса Ривза (автора Compojure) в поддержку изменения.


В конечном счете, как и все пространства имен, это функция предотвращения столкновений. Код Clojure, который пишется в наши дни, не заботится о наличии «частных» ключевых слов, поэтому они не видят особого смысла; но хорошо иметь их в наличии, когда они могут что-то изменить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...