2013-01-14 6 views
8

Basierend auf der Kommandozeileneingabe muss ich einige Laufzeitkonstanten setzen, die eine Anzahl von Downstream-Funktionen verwenden wird. Der Code in diesen Funktionen kann in anderen Threads ausgeführt werden, sodass ich die Kombination "declare var und use binding macro" nicht in Betracht ziehe. Was sind die Vor-und Nachteile der Verwendung einer Var (mit alter-var-root) dafür im Vergleich zu einem Atom? Das heißt,var versus atom für Laufzeitkonstanten

(declare *dry-run*) ; one of my constants 

(defn -main [& args] 
    ; fetch command line option 
    ;(cli args ...) 
    (alter-var-root #'*dry-run* (constantly ...)) 
    (do-stuff-in-thread-pool)) 

gegen

(def *dry-run* (atom true)) 

(defn -main [& args] 
    ; fetch command line option 
    ;(cli args ...) 
    (reset! *dry-run* ...) 
    (do-stuff-in-thread-pool)) 

Wenn es eine weitere Option neben diesen beiden, die ich in Betracht ziehen sollten, würde gerne wissen.

Auch hätte ich am liebsten kein Initialwert für das Atom angegeben, da ich an anderer Stelle (mit dem CLI-Aufruf) Standards setzen möchte, aber ich kann damit leben, vor allem, wenn das Atom Vorteile im Vergleich bietet zu den Alternativen.

Antwort

3

AFAIK alter-var-root garantiert nur die synchronisierte Änderung der Variablenwerte und garantiert keine sichere Lesung während dieser Änderung. Auf der anderen Seite bietet die atom wirklich atomare Änderung des Zustands der Identität.

Wenn Sie nicht wollen, einen Anfangswert liefern können Sie nur setzen Sie ihn auf nil:

(def *dry-run* (atom nil)) 
6

Write-once-Werte sind genau die Use-Case-Versprechen sind für:

(def dry-run (promise)) 

(defn -main [] 
    (deliver dry-run true)) 

(defn whatever [f] 
    (if @dry-run 
    ...)) 
+0

Danke für Ihren Tipp. Wird der Wert des Versprechens in allen Threads sichtbar sein (automatischer Bindungstransport), oder muss ich etwas Besonderes dafür tun? – Don

+0

Verbindendes Transportmittel kommt für nichts als vars ins Bild. Ein Versprechen ist nur ein Clojure-Objekt, das bei der Dereferenzierung den Wert erzeugt, der ihm geliefert wurde, oder blockiert, bis ein solcher Wert eintrifft. Threads sind nicht relevanter, als wenn Sie eine globale Hash-Map definiert hätten. – amalloy

2

Was ist falsch daran, nur eine var und alter-var-root zu verwenden? Sie legen den neuen Wert in Ihrer Startfunktion fest, bevor Sie die Worker wirklich starten. Es gibt also kein Rennen im Lesen. Und Sie können die @ überall dort speichern, wo Sie den Wert benötigen.

+0

Danke für Ihre Antwort. Das ist was ich gedacht habe.. – Don