Search code examples
clojuredynamic-binding

Difference between with-local-vars and with-bindings in Clojure


The documentation for Clojure with-local-vars and with-bindings doesn't suffice for me to distinguish the two. Any hints?


Solution

  • New vars are temporarily created by with-local-vars. Existing vars are temporarily rebound by with-bindings. In both cases the bindings are thread-local.

    Note that with-bindings is, as far as I can tell, primarily useful as a helper to pass bindings from another context by using a map returned by get-thread-bindings. The similar function binding would be more typical when not importing bindings.

    Illustrative examples:

    (binding [*out* (new java.io.StringWriter)] 
      (print "world!") (str "hello, " *out*))
    ;=> "hello, world!"
    
    (with-local-vars [*out* (new java.io.StringWriter)] 
      (print "world!") (str "hello," *out*))
    ;=> world!"hello,#<Var: --unnamed-->"
    
    (with-local-vars [foo (new java.io.StringWriter)] 
      (.write @foo "world") (str "hello, " @foo))
    ;=> "hello, world"
    
    (binding [foo (new java.io.StringWriter)] 
      (.write @foo "world") (str "hello, " @foo))
    ;=> CompilerException java.lang.RuntimeException: 
    ;     Unable to resolve var: foo in this context...