2015-10-15 14 views
8

In Clojure, se si chiama una funzione prima della sua definizione, ad es.Clojure: Perché una funzione dovrebbe essere `declare` se viene chiamata prima della definizione nel codice sorgente

(foo (bar 'a)) 

(defn bar [] ...) 

non compilato. Uno dovrebbe aggiungere

(declare bar) 

prima di (foo (bar 'a)). Perché Clojure è progettato come questo? Voglio dire, nella maggior parte dei linguaggi, eccetto C/C++, come Java, Python, PHP, Scala, Haskell o anche altri Lisps, specialmente nei linguaggi di tipo dinamico, la dichiarazione delle funzioni non è necessaria, cioè la definizione della funzione potrebbe essere prima o dopo una chiamata. Lo sento scomodo da usare.

risposta

13

Clojure fa una compilation single-pass (pure io semplificare, leggere il seguente link):

Così sembra logico che se si legge l'unica fonte una volta, dall'alto verso il basso, non è possibile avere cose come la dichiarazione anticipata e farlo in sicurezza.

citare Rich (primo link):

Ma, quello che dovrebbe accadere qui, quando il compilatore non ha mai visto prima bar?

`(defn foo [] (bar))` 

o in CL:

`(defun foo() (bar))` 

CL compila felicemente, e se non è mai definito bar, si verifica un errore di esecuzione. Ok, ma quale cosa reificata (simbolo) ha usato per la barra durante la compilazione? Il simbolo ha internato quando il modulo è stato letto. Quindi, cosa succede quando ottieni l'errore di runtime e rendi conto che la barra è definita in un altro pacchetto che hai dimenticato di importare . Si tenta di importare altri pacchetti e, BAM !, un altro errore - conflitto, altro pacchetto: la barra è in conflitto con il pacchetto read-in: bar. Quindi, , impari a conoscere uninterning.

In Clojure, il modulo non viene compilato, si ottiene un messaggio e nessuna var è internata per barra. Hai bisogno di altro spazio dei nomi e continua.

Preferisco di gran lunga questa esperienza, e quindi ha fatto questi compromessi. Molti altri vantaggi derivano dall'uso di un lettore non interno e dall'internamento solo su definizione/dichiarazione. Non sono propenso a rinunciarvi, né i benefici menzionati in precedenza, per supportare il riferimento circolare.

+1

Eccellente che hai tirato fuori questi vecchi post HN con le spiegazioni di Rich Hickey. Stavo cercando di ritrovarli ancora per molto tempo. –

+2

Significa anche che siete costretti a leggere il codice in modo coerente, vale a dire dal basso verso l'alto. Se guardi una funzione, allora sai che tutte le dichiarazioni al suo interno saranno sopra di esso nello spazio dei nomi, solo una piccola cosa ma è utile quando leggi il codice. – shmish111

Problemi correlati