Difference between binding and with-redefs

32 views
Skip to first unread message

Yehonathan Sharvit

unread,
Dec 25, 2018, 12:55:36 AM12/25/18
to Elements of Clojure
Hi Zach,

I really love your book!

A question related to the remark about with-redefs at the end of the section: "No one should have to know you’ve used binding".
The remark is: "However, any dynamic var invites re-binding; it may be safer to use with-redefs instead."

Can you clarify the difference between binding and with-redefs. I understand that with-redefs work also with non-dyanmic vars, but I don't understand in what cases with-redefs is safer than binding.

I have made for myself a minimal code snippet to see the danger of binding in combination with lazy sequences:


user=> (def ^:dynamic *a* 88)
#'user/*a*
user
=> (def b (binding [*a* 1] (map (fn [_] *a*) [1 2 3])))
#'user/b
user
=> b
(88 88 88)



But the issue also occur with with-redefs:


user
=> (def a 88)
#'user/a
user
=> (def b (with-redefs [*a* 1] (map (fn [_] *a*) [1 2 3])))
#'user/b
user
=> b
(88 88 88)



My question is: in what cases with-redefs is safer than binding?
 

Zach Tellman

unread,
Dec 25, 2018, 1:57:09 AM12/25/18
to Yehonathan Sharvit, Elements of Clojure
Where `binding` overrides a dynamic var within the current thread, `with-redefs` overrides any var across all threads.  This is incredibly unsafe to do within most production environments, but for testing it can be quite useful:

(deftest test-client-error-handling
  (with-redefs [app/server-handler failing-handler]
    ...))

This globally overrides the `app/server-handler` for the entire lifecycle of the test (which we control, unlike the examples in the `binding` sub-chapter).  By using `with-redefs`, we allow ourselves not to care about the server's threading model; if we used `binding` we'd be implicitly assuming that `app/server-handler` is dereferenced on the current thread.

Hope that helps,
Zach

--
You received this message because you are subscribed to the Google Groups "Elements of Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elements-of-clo...@googlegroups.com.
To post to this group, send email to elements-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elements-of-clojure/b4c1beed-b9b2-4d8d-870c-337cacf4264b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Yehonathan Sharvit

unread,
Dec 27, 2018, 12:36:27 AM12/27/18
to Elements of Clojure
It makes sense. Thank you for the clarification.
To unsubscribe from this group and stop receiving emails from it, send an email to elements-of-clojure+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages