2012-01-19 7 views
23

Więc pomyślałem, że byłoby miło wymyślić nazwę funkcji, która oblicza wykładniczy ^, ale wygląda na to, że karetka robi coś specjalnego, ponieważ Clojure REPL generuje błąd podczas oceny '^. Googlowanie głównie dało mi this, więc zastanawiałem się, co właściwie jest w użyciu dla karetki w Clojure.Clojure caret jako symbol?

(także możliwe byłoby po wszystkim wymienić funkcję ^?)

Odpowiedz

32

^ jest „meta znak” mówi the reader aby dodać symbol rozpoczynający się ^ jako metadane do kolejnego symbolu (pod warunkiem, że jest coś, co realizuje IMetas)

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

można się wiele dowiedzieć o pracach jak Clojure pod maską patrząc na meta rzeczy, na przykład funkcje:

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

to jest bardzo często wykorzystywane do type hints

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

jest ogólnie dobry pomysł, aby włączyć ostrzeżenia odbicia (set! *warn-on-reflection* true) a potem dodać podpowiedzi typu aż ostrzeżenia odejść. bez nich Clojure będzie sprawdzać typ funkcji operandów w czasie wykonywania, co oszczędza kłopotów związanych z typowaniem przy niewielkim koszcie.

PS: Moja następna postać ulubionego czytnika jest znak „wysyłka” #, to warto o tym następny nauki :)

PPS: jest różny w Clojure vs 1.2.x 1.3.x w Clojure Clojure 1.2.1 metadane nie komponować podczas korzystania z meta-znak:

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

i 1.3 „robi to, co trzeba”, a także słowa kluczowe są opcje zamiast „tagów”:

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

To nie jest dokładnie "dodaj symbol". Symbol jest skrócony dla typu int. Ale działa to również w przypadku łańcuchów, np. '^" B [". Słowa kluczowe są tłumaczone na opcje, np. '^: foo' zmienia się w' {: foo true} '. I wreszcie możesz określić samą mapę, np. '^ {: tag String: foo true: bar: baz}'. – kotarak

+0

dobry punkt kotarak, powinniśmy również wspomnieć, że metadane komponują się w różny sposób w różnych wersjach clojure i uważam, że 1.3 zaczyna kopiować łączące przykręcone metadane '^: foo ^: bar [1 3 4]' –

0

Wydaje mi się, że odpowiedź na twoje pytanie jest, niestety, nie. W Clojure nie można nazwać funkcji ^.

Próbowałem następujących w REPL:

user=> (println \^) 
^ 
nil 

To zdaje się sugerować, że można uciec karat (^) z odwrotnym ukośnikiem. Jednak, gdy próbuję zadeklarować funkcję używając \^ jako nazwa następnie pojawia się komunikat o błędzie:

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) 

Ten sam kod działa z regularnych nazwy tekstem:

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

Byłbym zachwycony, gdyby ktoś o lepszym Clojure-fu niż mój mógłby mi udowodnić, że się mylę! :)