Clojure карет как символ? - PullRequest
30 голосов
/ 19 января 2012

Так что я подумал, что было бы неплохо назвать функцию, которая вычисляет экспоненту ^, но похоже, что каретка на самом деле делает что-то особенное, так как Clojure REPL генерирует ошибку при оценке '^.В основном поиск в Google дал мне это , так что мне было интересно, какова на самом деле польза для каретки в Clojure.

(Кроме того, можно ли все-таки назвать функцию ^?)

Ответы [ 2 ]

40 голосов
/ 19 января 2012

^ - это «метасимвол», который он сообщает читателю , чтобы добавить символ, начинающийся с ^ в качестве метаданных, к следующему символу (при условии, что это то, что реализует 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 против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}
0 голосов
/ 05 августа 2015

Мне кажется, что ответ на ваш вопрос, к сожалению, нет. В Clojure вы не можете назвать функцию ^.

Я попробовал следующее в REPL:

user=> (println \^)
^
nil

Это означает, что вы можете избежать карата (^) с помощью обратной косой черты. Однако, если я пытаюсь объявить функцию, используя \^ в качестве имени, я получаю сообщение об ошибке:

user=> (defn \^ [n e] (cond (= e 0) 1 :else (* n (\^ n (- e 1)))))
IllegalArgumentException First argument to defn must be a symbol
clojure.core/defn (core.clj:277)

Тот же код работает с обычным текстовым именем:

user=> (defn exp [n e] (cond (= e 0) 1 :else (* n (exp n (- e 1)))))
#'user/exp
user=> (exp 3 3)
27

Я был бы рад, если бы кто-то с лучшим Clojure-fu, чем мой, мог доказать, что я неправ! :)

...