Search code examples
clojuredynamic-rebinding

When should one use the temporarily-rebind-a-special-var idiom in Clojure?


I've noticed that some libraries such as clojure-twitter use special vars (the ones intended for dynamic binding that are surrounded by asterisks) for oauth authentication. You save your authentication in a var and then use (with-oauth myauth ..). I think this is a very nice solution to this sort of problem, because you can rebind the auth var for each user of the application.

I've taken a similar route in an email client I've been writing. I have a special var named session that I bind to a map with the current user's session, and user info, and there are various important functions that use information from that var. I wrote a macro, with-session to temporarily rebind it in the context of a set of forms passed to with-session. It turns out to be a pretty clean solution (to me).

So, my question is this: am I 'doin' it rite'? Is this a bad design decision, or is this one of the intended usages of special vars?


Solution

  • You seem to be doing it exactly right. In fact, there's a number of built-in / contrib macros which work similarly, say with-out-str or clojure.contrib.sql/with-connection. The latter is a rather key part of present day Clojure infrastructure, so whatever idioms it uses have been scrutinised by a lot of people.

    The important gotcha to keep in mind is that threads you launch while in scope of a bindings / with-bindings form do not inherit the rebound values for the vars in question; rather, they see the root bindings. If you want to propagate your bindings to worker threads / agents, either pass them on explicitly (as function arguments, say) or use bound-fn.