Ответ 1
^
является "метасимволом", он говорит читателю добавить символ, начинающийся с ^
как метаданные, к следующему символу (если это то, что реализует IMetas)
user=> (def x ^:IamMeta [1 2 3])
#'user/x
user=> x
[1 2 3]
user=> (meta x)
{:tag :IamMeta}
user=>
Вы можете много узнать о том, как clojure работает под капотом, глядя на meta
-вещи, например функции:
user=> (meta foo)
{:ns #<Namespace user>,
:name foo, :file "NO_SOURCE_PATH",
:line 5, :arglists ([s])}
это очень часто используется для подсказок типа
(defn foo [^String s] (.charAt s 1))
обычно рекомендуется включать предупреждения отражения (set! *warn-on-reflection* true)
а затем добавлять подсказки типа до тех пор, пока предупреждения не исчезнут. без этих Clojure будет искать тип функциональных операндов во время выполнения, что избавит вас от проблем с типами, хотя и с небольшими затратами.
PS: Мой следующий любимый персонаж читателя - это символ "отправки" #
, он стоит узнать об этом дальше :)
PPS: это отличается от clojure 1.2.x vs clojure 1.3.x в Clojure 1.2.1 метаданные не создаются, когда вы используете метасимвол:
user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:tag :foo}
и в 1.3 он "делает правильную вещь", а также ключевые слова - это опции вместо "тегов":
user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:foo true, :bar true}