Lancet's runonce function needs to wrap a function with runs-only-once  
semantics, *and* make subsequent callers wait for the return value  
before proceeding. There was a thread on this last November where Rich  
explained several approaches 
(http://groups.google.com/group/clojure/msg/406be93eb0a226aa 
).

None of those approaches quite fit what Lancet needs. However, this  
locking approach works (I think):

(defn runonce
"Create a function that will only run once. All other invocations
  return the first calculated value. The function *can* have side  
effects,
  and calls to runonce *can* be composed. Deadlock is possible
  if you have circular dependencies.
  Returns a [has-run-predicate, reset-fn, once-fn]"
  [function]
  (let [sentinel (Object.)
        result (atom sentinel)
        reset-fn (fn [] (reset! result sentinel))
        has-run-fn (fn [] (not= @result sentinel))]
    [has-run-fn
     reset-fn
     (fn [& args]
       (if (= @result sentinel)
         (locking sentinel
           (if (= @result sentinel)
             (reset! result (function))))))]))

Is this an example where locking is reasonable, or is there a better  
Clojurish way?

Stuart

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to