Hi,
On Aug 10, 1:12 pm, Laurent PETIT <
laurent.pe...@gmail.com> wrote:
> Also, wouldn't it be interesting to provide a macro whose purpose would be
> to just encapsulate an existing fn ? This could then allow functions whose
> purpose is to delegate processing to other threads for technical rather than
> business reasons (think pmap) to encapsulate the whole thread binding
> information just before quitting the "business" thread ?
*oerk* Swallowing the own pill...
> (defn bound-fn*
> "Returns a function, which will install the same bindings in effect as
> in the thread at the time bound-fn* was called. This may be used to define a helper
> function which runs on a different thread, but needs the same bindings
> in place."
> [f]
> (let [bindings (get-thread-bindings)]
> (fn [& args]
> (binding* bindings f args))))
^ + apply
(defmacro bound-fn
[& fntail]
`(bound-fn* (fn ~@fntail)))
However this would not allow for recursive calls, which happen delayed
as I explained in the comment for the ticket.
Hmm... How about restructuring the whole thing and going away with the
nameing from binding all together? The difference between with-
bindings
and binding would be, that with-bindings takes (maybe at runtime
defined)
map instead of a vector.
(defn with-bindings*
"Takes a map of Var/value pairs. Installs for the given Vars
the associated values as thread-local bindings. Then calls f
with the supplied arguments. Pops the installed bindings
after
f returned. Returns whatever f returns."
[binding-map f & args]
(push-thread-bindings binding-map)
(try
(apply f args)
(finally
(pop-thread-bindings))))
(defmacro with-bindings
"Takes a map of Var/value pairs. Installs for the given Vars
the associated values as thread-local bindings. The executes
body. Pops the installed bindings after body was evaluated.
Returns the value of body."
[binding-map & body]
`(with-bindings* ~binding-map (fn [] ~@body)))
(defn bound-fn*
"Returns a function, which will install the same bindings in
effect as in the thread at the time bound-fn* was called and
then call f with any given arguments. This may be used to
define a helper function which runs on a different thread,
but
needs the same bindings in place."
[f]
(let [bindings (get-thread-bindings)]
(fn [& args]
(apply with-bindings* bindings f args))))
(defmacro bound-fn
"Returns a function defined by the given fntail, which will
install the same bindings in effect as in the thread at the
time bound-fn was called. This may be used to define a
helper
function which runs on a different thread, but needs the
same bindings in place."
[& fntail]
`(bound-fn* (fn ~@fntail)))
Then a seq generating function, relying on some thread-local bindings,
could be written as:
(defn my-hypothetical-seq
[coll]
(let [bindings (get-thread-bindings)
step (fn step [s]
(lazy-seq
(with-bindings bindings
(generate-seq-here-calling-step))))]
(step coll)))
What do you think?
Sincerely
Meikel