2012-01-19 9 views
23

Así que pensé que sería una buena idea nombrar una función que calcula el exponencial ^, pero parece que el cursor realmente hace algo especial, ya que Clojure REPL genera un error al evaluar '^. Google en su mayoría me dio this, por lo que me preguntaba cuál es el uso real para el caret en Clojure.Clojure caret como un símbolo?

(También, sería posible después de todo, para nombrar una función ^?)

Respuesta

32

^ es "el carácter meta" que dice the reader añadir el símbolo a partir de ^ como metadatos para el siguiente símbolo (siempre y cuando es algo que implementa IMetas)

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

Usted puede aprender mucho acerca de cómo funciona la clojure bajo el capó mirando el meta de las cosas, para las funciones de ejemplar: 012

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

esto es muy a menudo utilizado para type hints

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

lo general es una buena idea para encender las advertencias reflexión (set! *warn-on-reflection* true) y luego añadir más consejos de tipo hasta que las advertencias desaparecen. sin estos, Clojure buscará el tipo de operandos de función en tiempo de ejecución, lo que le ahorrará la molestia de preocuparse por los tipos, aunque a un bajo costo.

PS: Mi siguiente carácter lector favorito es el carácter "expedición" #, es bien vale la pena aprender sobre él :) próximos

PPS: esto es diferente en clojure 1.2.x 1.3.x vs clojure en clojure 1.2.1 metadatos no compone cuando se utiliza el meta-caracteres:

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

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

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

No es exactamente "agregar el símbolo". Un símbolo es un atajo para un tipo int. Pero esto también funciona con cadenas, ej. '^" B ["'. Las palabras clave se traducen a opciones, ej. '^: foo' se convierte en' {: foo true} '. Y finalmente puedes especificar un mapa en sí, ej. '^ {: tag String: foo true: bar: baz}'. – kotarak

+0

buen punto kotarak, también deberíamos mencionar que los metadatos se componen de manera diferente en las diferentes versiones de clojure y creo que 1.3 comienza a copiar los metadatos encadenados '^: foo ^: bar [1 3 4]' –

0

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

He intentado lo siguiente en el REPL:

user=> (println \^) 
^ 
nil 

Esto parece dar a entender que se puede escapar el quilate (^) con una barra invertida. Sin embargo, si trato de declarar una función usando \^ como un nombre, entonces me sale 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 normal:

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

Estaría encantado si ¡Alguien con mejor Clojure-fu que el mío podría demostrar que estoy equivocado! :)

Cuestiones relacionadas