It sounds like you want a delay. Delays are guaranteed to execute their
body only once, so we can combine a delay with an atom:

(defn memoized [f]
  (comp deref (memoize (fn [& args] (delay (apply f args)))))

In theory that should produce a memoize that executes the function only
once for each set of arguments.

- James

On 6 December 2014 at 21:32, Andy L <core.as...@gmail.com> wrote:

> Hi,
>
> Here is the situation. There is a function "f" retrieving some data from
> various sources (including reading files, a lot of io, e.g. map-reduce)
> expected by design to return the same result for given input. Results of
> "f" invocation from parallely running futures are stored in an atom wrapped
> map and everything works just fine.
>
> With a small exception when "f" invocations with the same arguments
> overlap  - the same expensive "io" is kicked off 2 or more time s. Not a
> tragedy, but still very unpleasant and wasteful. The expectation would be
> that a subsequent "f" call would just bail without doing anything while
> initial invocation assoc new data into an atom,
>
> The first intuition was to use memoize, however I do not think its
> semantics fit well into this case, since the result is a "side-effect" on
> an atom as opposed to return value.
>
> The easiest solution, is to create another atom with a map of the
> arguments into a "state". If some other "future" is already there working
> hard on the problem, we simply bail. However, that leads to another problem.
>
> "compare-and-set!" just operates on atoms as wholes, which is fine for
> unstructured data, but .... falls short for things somewhat more complex,
> like here.
>
> While updating an atom in this context is trivial:
>
> user=> (def a (atom {}))
> user=> (swap! a assoc ["arg1" "arg2"] :PENDING)
> {["arg1" "arg2"] "resultA"}
>
> I would like to link the condition and future together somehow like that:
>
> user=> (when ((complement contains?) @a ["arg1" "arg3"]) (swap! a assoc
> ["arg1" "arg3"] :PENDING ))
>
> That obviously will not work, unless I wrap it with "locking", which is
> not necessarily a nice thing to do. I also tried to use refs here, however
> they do not fit well here either and the solution is not as nice as it
> could be.
>
> After that long introduction, I would like ask for some insight ....
> Thanks in advance ...
>
>
> Best,
> Andy
>
>
>
>
>
>
>
>
>
>
>
>  --
> 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
> Note that posts from new members are moderated - please be patient with
> your first post.
> 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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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
Note that posts from new members are moderated - please be patient with your 
first post.
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to