2013-11-15 24 views
5

Vorrei chiedere umilmente ...var o ref/atom/agent per valori costanti?

Cosa, "var o ref/atom/agent per valori costanti?", Chiedo? Certo, io uso vars per i valori costanti.

Ma mi sono sempre chiesto quale dei due dovrei usare quando i valori si comportano come costanti ma dovrebbero essere assegnati in fase di esecuzione, piuttosto che in fase di compilazione (quando i codici vengono letti).

Ad esempio, pensare alcune proprietà java scritte nel file di configurazione dell'utente. Dovrebbero essere assegnati in fase di esecuzione perché i dati non sono nei codici. Ma dovrebbero anche essere definiti prima che i dati vengano letti, poiché gli altri codici li riferiscono.

In questo caso,

quando si usa 'di var ?:

  • io definisco' var di, o semplicemente dichiaro 'var di (quando va bene).
  • E poi ridefinisco quelle 'var' di nuovo con le funzioni che leggono i file di opzioni.
  • Ma è terribile sovrascrivere 'var's, o sembra strano definire' le funzioni interne di var.

Quando posso utilizzare ref/atom/agente ?:

  • assegno ref/atom/agenti di 'var di.
  • Quindi aggiorno tali riferimenti/atom/agenti per funzioni che leggono i file di opzioni.
  • Ma dal momento che i valori sono utilizzati in tutto il programma, quindi mi preoccupo i loro costi.
  • ... e l'utilizzo di troppi @ macro è alquanto fastidioso.

Non so cosa dovrei usare.

Che cosa usi in questi casi?

'var's? 'Ref/atom/agente? o anche 'ritardo?

Grazie in anticipo.

+0

Perché non definire la var sincrono alla prima linea quando si avvia il programma? Così in questo caso non hai bisogno di sovrascrivere quella var da qualche altra parte, dall'altra parte se sei fastidioso scrivendo '@ My-var' ovunque appena possibile definire una funzione wrapper che restituisce' @ my-var' – hsestupin

+0

Grazie per la risposta. Come definisco la mia var in modo sincrono? Non credo di capire cosa intendi. Pensavo che i vars non fossero qualcosa di sincrono. Intendevi assegnare i ref a vars e resettare (aggiornare) i ref per l'inizializzazione? –

+1

Voglio dire al vostro namespace 'ns.with-const' con quella costante prima riga di codice sarebbe' (DEF my-const (alcuni-calcoli)) '. Quindi finché questa espressione non sta valutando tutti gli spazi dei nomi che cercano di usare o richiedere 'ns.with-const' non inizieranno a valutare il proprio codice. E non ci sono condizioni di gara con questo modello. Quando il tuo const sarà calcolato, diventa definito e tutto funziona perfettamente. Spero che questa spiegazione abbia senso – hsestupin

risposta

2

Se tutto, o un gruppo, di "costanti", che stai prendendo in considerazione, possono essere apprese in un singolo punto nel tempo, chiamiamole "proprietà".

E facciamo un config che "li risucchiare":

(defn resource [path] 
    (when path 
    (-> (Thread/currentThread) .getContextClassLoader (.getResource path)))) 

(def props 
    (edn/read-string 
    (slurp (io/file (resource (System/getProperty "your.conf")))))) 

(defn conf [& path]     ;; e.g. (conf :db :uri) 
    (get-in props (vec path))) 

le proprietà (ad esempio "costanti") il file "il vostro.conf" sarebbe nelle linee di:

{:db 
    {:uri "datomic:mem://dbname" 
    :other-property 42} 

:rabbit 
     {:host "192.168.1.17" 
     :port 5672 
     :exchange "xyz-exchange" 
     :queue "zq" 
     :exchange.type "direct" 
     :vhost "/some-broker" 
     :username "user" 
     :password "strong"}} 

Poi più tardi nel programma/altri spazi dei nomi è possibile accedere a tutti gli annunci di questo come:

(conf :db :uri)    ;; will "constant"ly return "datomic:mem://dbname" 
(conf :rabbit :host)   ;; will "constant"ly return "192.168.1.17" 
(conf :db :other-property) ;; will "constant"ly return 42 

nella 'vita reale', i 'props' var sopra sarebbe potenzialmente il controllo di un percorso "-D", hanno valori di default, e gestire le eccezioni, ma è un po 'semplificato per illustrare il punto.