clojure caret

Clojure caret como un símbolo?



(2)

Me parece que la respuesta a su pregunta es, desafortunadamente, no. En Clojure, no puedes nombrar una función ^ .

He intentado lo siguiente en el REPL:

user=> (println /^) ^ nil

Esto parece implicar que puedes escapar del quilate ( ^ ) con una barra invertida. Sin embargo, si trato de declarar una función usando /^ como nombre, aparece un mensaje de error:

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)

El mismo código funciona con un nombre de texto regular:

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

¡Me encantaría que alguien con mejor Clojure-fu que el mío pudiera demostrar que estoy equivocado! :)

Así que pensé que sería una buena idea nombrar una función que calcula el exponencial ^ , pero parece que el caret realmente hace algo especial, ya que el REPL de Clojure genera un error al evaluar ''^ . La mayoría de las búsquedas en Google me dieron this , así que me preguntaba cuál es el uso real del caret en Clojure.

(Además, ¿sería posible, después de todo, nombrar una función ^ ?)


^ es "el metacarácter", le dice al lector que agregue el símbolo que comienza con ^ como metadatos al siguiente símbolo (siempre que sea algo que implemente IMetas)

user=> (def x ^:IamMeta [1 2 3]) #''user/x user=> x [1 2 3] user=> (meta x) {:tag :IamMeta} user=>

Puede aprender mucho sobre cómo funciona el clojure bajo el capó mirando el meta de las cosas, por ejemplo, las funciones:

user=> (meta foo) {:ns #<Namespace user>, :name foo, :file "NO_SOURCE_PATH", :line 5, :arglists ([s])}

Esto se usa muy a menudo para sugerencias de tipo.

(defn foo [^String s] (.charAt s 1))

por lo general, es una buena idea activar las advertencias de reflexión (set! *warn-on-reflection* true) y luego agregar sugerencias tipográficas hasta que desaparezcan las advertencias. sin estos, Clojure buscará el tipo de operandos de la función en tiempo de ejecución, lo que le ahorra la molestia de tener problemas con los tipos, aunque a un costo leve.

PD: Mi próximo personaje de lector favorito es el número de "envío", vale la pena aprenderlo a continuación :)

PPS: esto es diferente en clojure 1.2.x vs clojure 1.3.x en Clojure 1.2.1 los metadatos no se componen cuando se usa el meta-carácter:

user=> (def foo ^:foo ^:bar [1 2 3]) #''user/foo user=> (meta foo) {:tag :foo}

y en 1.3 "hace lo correcto" y también las palabras clave son opciones en lugar de "etiquetas":

user=> (def foo ^:foo ^:bar [1 2 3]) #''user/foo user=> (meta foo) {:foo true, :bar true}