Skip to content

Instantly share code, notes, and snippets.

@quan-nh
Last active April 12, 2022 10:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save quan-nh/f273829a28576c326c86aea6079b0084 to your computer and use it in GitHub Desktop.
Save quan-nh/f273829a28576c326c86aea6079b0084 to your computer and use it in GitHub Desktop.
Understanding the difference between lexical and dynamic scope in Clojure.

concept

  • lexical scope (static scope): dependent only on the program text.
  • dynamic scope: dependent on the runtime call stack.

clojure

  • (def x 1) default Var is static, using let for local Var, with-redefs to change the root binding var within its scope (visible in all threads).
  • (def ^:dynamic x 1) dynamic Var, using binding to change value (thread-local, cannot be seen by any other thread).

In example bellow:

  • binding only changes the value of *dynamic-var* within the scope of the binding expression
  • def changes the root definition of non-dynamic-var from the point of execution on
  • using let to rebind non-dynamic-var, the change is only local and won’t affect the top-level non-dynamic-var
(def non-dynamic-var "this is a non dynamic var")
(def ^:dynamic *dynamic-var* "this is a dynamic var")

(defn function-using-dynamic-var []
  (println *dynamic-var*))

(defn function-using-non-dynamic-var []
  (println non-dynamic-var))

(defn some-function []

  (function-using-dynamic-var) ;;=> this is a dynamic var
  
  ;; dynamically rebind dynamic-var
  (binding [*dynamic-var* "this is some new content for the dynamic var"]
    (function-using-dynamic-var)) ;;=> this is some new content for the dynamic var


  (function-using-non-dynamic-var) ;;=> this is a non dynamic var
  
  ;; locally rebind non-dynamic-var
  (let [non-dynamic-var "this is some new content that won't be used"]
    (function-using-non-dynamic-var)) ;;=> this is a non dynamic var
    
  ;; lexically (and globally) rebind non-dynamic-var
  (def non-dynamic-var "this is some new content that will be used")
  (function-using-non-dynamic-var) ;;=> this is some new content that will be used
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment