You should be able to do this without the ref. Have the agent's state  
contain a pair of [has-run, fn-result].

Stuart

> Hi,
>
> Am 09.11.2008 um 12:23 schrieb Stuart Halloway:
>> Just to make things even more fun: *None* of the proposed fixes to  
>> the
>> concurrency bug in the original actually preserve the` semantics of
>> the original. All have moved from "run (usually) once, mark as done"
>> to "mark as done, try once". This also means that other threads could
>> see a runonce as being done when it hasn't begun yet.
>
> Hmm.. I have no clue about concurrent programming whatsoever. But
> for such cases, maybe an agent would do the trick. Send it the action.
> The first time it runs, it calls the function and caches the result.
> This could be done maybe with delay/force. Multiple sends would be
> automatically be syncronised. But to get the result out of the agent
> one would have to pass in a ref, where the results are stored.
>
> (defmacro defrunonce
>  [n & body]
>  `(def ~n
>     (let [agent# (agent (delay [EMAIL PROTECTED]))
>           retr#  (fn [state# r-ref#]
>                    (let [r# (force state#)]
>                      (dosync (ref-set r-ref# r#))))]
>       (fn []
>         (let [r-ref# (ref nil)]
>           (send agent# retr# r-ref#)
>           (await agent#)
>           (deref r-ref#))))))
>
> user=> (defrunonce foo (println :Run) 5)
> #=(var user/foo)
> user=> (foo)
> :Run
> 5
> user=> (foo)
> 5
>
> Ok. Maybe this is also only a hack.
>
> Sincerely
> Meikel
>
>


--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to