2015-08-28 15 views
9

Sono curioso perché questo funziona (come mi sarei aspettato che dopo aver letto the documentation on the dot special form):di Clojure dot forma particolare stranezza

(map #(. % isInstance {}) [clojure.lang.IPersistentMap]) 

rendimenti:

(true) 

ma questo non significa:

(. clojure.lang.IPersistentMap isInstance {}) 

Viene visualizzato un messaggio di errore, "Nessun metodo di abbinamento: isInstance". La forma è esattamente la stessa della chiamata di funzione map sopra, ma al di fuori di map, non funziona. Perché?

risposta

6

La forma speriale . (punto) è la più strana di tutte. Non sono sicuro se lo spiegherò bene, ma proviamo.

Per docs:

Se il primo operando è un simbolo che si risolve in un nome di classe, l'accesso è considerato a un membro statico della classe denominata. Nota che le classi annidate sono nominate EnclosingClass $ NestedClass, secondo le specifiche JVM. Altrimenti si presume che sia un membro di istanza e il primo argomento viene valutato per produrre l'oggetto di destinazione.

Enfasi mia.

Quindi si ha colpito il primo caso con (. clojure.lang.IPersistentMap isInstance {}) - clojure.lang.IPersistentMap si risolve in nome classe e si presuppone che l'intera espressione sia una chiamata di metodo statico.

Nel caso map il simbolo viene valutato (la parte con enfasi), viene valutato nell'oggetto classe clojure.lang.IPersistentMap prima di essere passato alla funzione anonima e l'intera espressione è una chiamata al metodo di istanza su tale classe.

Quindi si riduce al fatto che in un punto lo clojure.lang.IPersistentMap viene utilizzato come un simbolo che fa riferimento a un nome di classe e nell'altro come qualcosa che valuta un oggetto di classe.

Vedi anche here:

notare che i nomi delle classi normalmente denotano oggetti di classe, ma vengono trattati in maniera particolare in certe forme speciali, per esempio '' e nuovo.

+3

Questa spiegazione è corretta Vorrei solo aggiungere che è possibile forzare il compilatore a considerare l'oggetto classe facendo '(. (Do clojure.lang.IPersistentMap) isInstance {})' (tra gli altri modi). Tuttavia la forma speciale '.' (e' new' too) è di livello molto basso e, a meno che tu non stia scrivendo alcuni macro di interoperabilità, non dovresti usarlo. Preferisco '.member',' constructor' e 'Class/staticMember' sugli usi diretti di' new' e '.'. Se sei curioso dovresti vedere come queste forme zuccherate espandi macro alle forme '.' e' new'. – cgrand