Warum sagt Clojure 1.3, dass Variablen nicht als dynamisch deklariert werden, wenn ich sie als dynamisch deklariert habe? [geschlossen]

  • Ich portiere den Clojure-Code (in einem Leiningen-Projekt) von 1.2 auf 1.3 und habe Probleme. Neben dem Code, der nicht mehr funktioniert, erhalte ich Dutzende von Warnmeldungen wie diese:

     Warning: *tooltip-width* not declared dynamic and thus is not dynamically rebindable, 
    but its name suggests otherwise. Please either indicate ^:dynamic *tooltip-width* 
    or change the name.
     

    Dies geschieht, obwohl ich bereits die korrekten Änderungen an vars vorgenommen habe, die ich zur Aufrechterhaltung des Zustands verwende. Für den obigen Fehler enthält der Code beispielsweise bereits Folgendes:

     (def ^:dyanamic *tooltip-width*   (* 1.8 *slip-width*))
     

    Ich bekomme diese Fehler an zwei Stellen : Zuerst über die Befehlszeile als Ergebnis der Ausführung von lein swank; und zweitens aus dem Emacs REPL, nachdem ich meine core.clj -Datei mit C-c C-w zusammengestellt habe.

    Um vollständig zu sein, hier meine project.clj -Datei:

     (defproject infwb "1.0.0-SNAPSHOT"
      :description "an evolving, experimental workspace for manipulating infocards"
      :main infwb.core
    
      :dependencies [[org.clojure/clojure "1.3"]
                 [seesaw "1.2.1"]
             [org.clojars.gw666/sxqj "beta2"]
             [org.clojars.gw666/piccolo2dcore "1.3"]
             [org.clojars.gw666/piccolo2dextras "1.3"]
             [com.miglayout/miglayout "3.7.4"]
             ]
      :dev-dependencies [[swank-clojure "1.3.2"]
                 [org.clojars.weavejester/autodoc "0.9.0"]]
      :autodoc {:name "Infocard Workbench (InfWb)",
            :web-src-dir "https://github.com/gw666/infwb/blob"})
     

    Neben der Funktionsweise meines Codes möchte ich auch verstehen, warum Ich bekomme diese Fehler und warum ich sie an beiden Orten bekomme. Vielen Dank für Ihre Hilfe.

    22 November 2011
    Gregg Williams
2 answers
  • Es ist ein einfacher Tippfehler.

     (def ^:dyanamic ...
     

    sollte sein:

     (def ^:dynamic ...
     

    Das passiert uns allen!

    22 November 2011
    Scott
  • Sie können erwägen, Refs oder Atome anstelle von vars zu verwenden, um den Status beizubehalten.

    Um die Clojure-Dokumentation :

    Vars bieten einen Mechanismus, um auf einen veränderbaren Speicherort zu verweisen, der dynamisch (an einen neuen Speicherort) gebunden werden kann Speicherort) pro Thread .

    (Hervorhebung meines.)

    Vars können mit dem Makro binding auf einen neuen Wert (für den aktuellen Thread) gesetzt werden. Bis zu Clojure 1.2 kann eine beliebige Var-Variante wie folgt abprallen, aber seit Clojure 1.3 müssen Vars explizit als ^:dynamic deklariert werden, um dies zuzulassen. (Soweit ich weiß, ist der Grund eine drastische Beschleunigung der Var-Suchvorgänge für den üblichen Fall, dass kein erneutes Binden erfolgt.)

    Dies ist eine übliche Konvention (aber nichts.) more) um Variablen zu geben, die als Rebound-Namen dienen sollen: *foobar*. Aufgrund dieser Konvention gibt der Compiler eine Warnung aus, wenn eine Variable mit diesem Namen angezeigt wird, die nicht als dynamisch deklariert ist.

    Fazit:

    • Wenn Sie nur einen Wert deklarieren möchten, der sich zur Laufzeit nicht ändert, verwenden Sie eine Var und legen Sie die * um den Namen.
    • Wenn Wenn Sie den Wert pro Thread ändern möchten, deklarieren Sie die Variable var.
    • Wenn Sie den globalen -Status (nicht pro Thread) beibehalten möchten, verwenden Sie einer der anderen referenziellen Typen: atom, ref (wenn Sie Transaktionen benötigen) oder agent (für asynchrone Änderung).
    22 November 2011
    Christian Berg