2012-01-19 24 views
23

Quindi ho pensato che sarebbe stata una buona idea denominare una funzione che calcola l'esponenziale ^, ma sembra che il caret faccia effettivamente qualcosa di speciale, poiché il REPL Clojure genera un errore durante la valutazione di '^. Googling per lo più mi ha dato this, quindi mi chiedevo quale sia l'uso effettivo per il cursore in Clojure.Il simbolo del Clojure è un simbolo?

(Inoltre, sarebbe possibile, dopo tutto per citarne una funzione ^?)

risposta

32

^ è "il carattere meta" dice the reader per aggiungere il simbolo a partire da ^ come metadati al simbolo successivo (a condizione che è qualcosa che implementa IMetas)

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

si può imparare molto su come funziona Clojure sotto il cofano, cercando al meta di cose, per le funzioni di esempio:

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

questo è molto spesso utilizzato per type hints

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

è generalmente una buona idea per accendere gli avvisi di riflessione (set! *warn-on-reflection* true) e quindi aggiungere tipo suggerimenti fino a quando gli avvertimenti andare via. senza questi Clojure cercherà il tipo di operandi della funzione in fase di esecuzione, il che ti eviterà il fastidio di affannarti con i tipi anche se con un leggero costo.

PS: Il mio prossimo personaggio reader preferito è il carattere "spedizione" #, vale la pena di apprendimento su di esso prossimi :)

PPS: questo è diverso in clojure 1.2.x vs clojure 1.3.x in Clojure 1.2.1 metadati non comporre quando si utilizza il meta-carattere:

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

e 1.3 che "fa la cosa giusta", e anche le parole chiave sono opzioni al posto di "tag":

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

Non è esattamente "aggiungi il simbolo". Un simbolo è scorciatoia per un tipo int. Ma questo funziona anche con le stringhe, ad es. '^ "B ["'. Le parole chiave sono tradotte in opzioni, ad es. '^: foo' è trasformato in' {: foo true} '. E infine è possibile specificare una mappa stessa, ad es. '^ {: tag String: foo true: bar: baz}'. – kotarak

+0

buon punto kotarak, dovremmo anche menzionare che i metadati si compongono diversamente nelle diverse versioni di clojure e credo che 1.3 inizi a copiare i metadati concatenati '^: foo ^: bar [1 3 4]' –

0

Mi sembra che la risposta alla tua domanda sia, sfortunatamente, no. In Clojure, non è possibile denominare una funzione ^.

ho provato quanto segue nella REPL:

user=> (println \^) 
^ 
nil 

Questo sembra implicare che si può sfuggire il carato (^) con una barra rovesciata. Tuttavia, se provo a dichiarare una funzione che utilizza \^ come un nome allora ottengo un messaggio di errore:

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) 

Lo stesso codice funziona con un nome di testo normale:

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

sarei felice se qualcuno con un Clojure-fu migliore del mio potrebbe dimostrarmi sbagliato! :)

Problemi correlati