On Nov 8, 2008, at 8:31 PM, Stuart Halloway wrote:
>
> The defrunonce macro below works, creating a function that runs only
> once and tracking its run status in metadata.
>
> Now, how do I write it without using eval?
>
> (defn runonce
> "Create a function that will only run once, given a function.
> Returns
> a vector containing the function and the reference that tracks
> whether
> the function has been run."
> [function]
> (let [has-run (ref false)]
> [(fn [& args]
> (or @has-run
> ; TODO: think through semantics for parallel target invocation
> (do
> (apply function args)
> (dosync (ref-set has-run true)))))
> has-run]))
Since the deref of has-run is outside a transaction, I don't see
anything here that prevents two threads from running function if
they're trying to do it at roughly the same time.
I think the following version accomplishes the core task of running
just once and could be adapted to return the has-run ref as well:
(defn runonce
"Create a function that will only run its argument once."
[function]
(let [has-run (ref false)]
(fn [& args]
(when
(dosync
(ensure has-run)
(when-not @has-run
(ref-set has-run true)))
(apply function args)))))
I'd appreciate seeing corrections or simplifications of it.
--Steve
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---