Почему использование ключевых слов или символов в качестве функций для поиска значений из карт работает? - PullRequest
21 голосов
/ 02 августа 2011

Цитата из Радость Clojure , раздел 4.3.1 -

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

(def population {:zombies 2700, :humans 9})
(:zombies population)
;=> 2700
(println (/ (:zombies population)
(:humans population))
"zombies per capita")
; 300 zombies per capita

Мне не очевидно, что здесь происходит. Каким-то образом (:zombies population) должен быть преобразован в (get population :zombies), верно? Как именно это работает? Ключевое слово оценивает себя, а не функцию. Обращает ли читатель внимание на случаи, когда первым в списке является ключевое слово, и добавьте get и переместите ключевое слово в конец списка?

Ответы [ 3 ]

24 голосов
/ 02 августа 2011

Цитата из официальная документация :

Ключевые слова реализуют IFn для invoke () одного аргумента (карты) с необязательным вторым аргументом (значение по умолчанию). Например, (: mykey my-hash-map: none) означает то же самое, что и (получить my-hash-map: mykey: none). Смотри получить.

И Clojure может вызывать ключевое слово как функцию, потому что он реализует тот же интерфейс, что и функция. То же самое для символов ...

18 голосов
/ 02 августа 2011

Ключевые слова являются функциями, во всех отношениях. Магия читателя не задействована, как вы увидите, если вы попробуете (let [m {:humans 100}, k :humans] (k m)). Я надеюсь, вы согласитесь, что читатель никак не сможет превратить это в get (компилятор может, но вы можете притвориться, что я сделал значение k зависимым от выражения if, которое компилятор не может предсказать, например, пользовательский ввод).

Поскольку основные типы данных Clojure являются интерфейсами, а объекты Java могут реализовывать множество интерфейсов, часть данных может иметь несколько типов. Это ключевое слово? Да. Это функция? Также да:

user> (keyword? :k)
true
user> (ifn? :k)
true
user> (.invoke :k {:k 1})
1
6 голосов
/ 02 августа 2011

Ключевые слова реализуют IFn,

https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java

и его метод invoke обрабатывает вызов get.

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