Hi Christophe,

your fifo-strategy (the one that uses "identity" as the hit method)
does not work:

user=> (def g (memoize7 identity (fifo-strategy 3)))
#'user/g
user=> (g 1)
1
user=> (g 1)
java.lang.IllegalArgumentException: Wrong number of args passed to:
core$identity (NO_SOURCE_FILE:0)

You have to use something like #(first %&) instead of identity.

memoize7 looks fine to me in terms of avoiding extra computation. I'm
not sure though why memoize6 exists as a fn in its own right. I guess
you wouldn't use it without something like delays, as the whole point
of memoize is to avoid multiple costly computations of the same thing,
and memoize6 does not always do that, unless you give it a fn f that
takes care of it, as memoize7 does.

If you don't rely on memoize6, you can write memoize7 even more
compact than memoize6, like this:

(defn memoize7-variant
 ([f] (memoize7-variant f [{} identity (fn [mem args] mem) assoc]))
 ([f [init cached hit assoc]]
  (let [mem (atom init)]
    (fn [& args]
      (deref ((cached
               (swap! mem (fn [mem]
                            (if (contains? (cached mem) args)
                             (hit mem args)
                             (assoc mem args (delay (apply f args)))))))
              args))))))

It's more compact, as we do the contains? (or in your original
version: "find") check only once inside the swap! function. This has
the (admittedly not really huge) added benefit that we don't create
multiple delays in the case of "bad luck", as mentioned in my earlier
post.

Any downsides to this?

Cheers
Eugen

On Mar 14, 9:26 am, Christophe Grand <christo...@cgrand.net> wrote:
> Hi Meikel,
>
> On Sat, Mar 13, 2010 at 10:51 PM, Meikel Brandmeyer <m...@kotka.de> wrote:
> > On Fri, Mar 12, 2010 at 08:27:15PM +0100, Christophe Grand wrote:
>
> > > See my memoize5: the call isn't computed inside the swap!s
>
> > That doesn't mean, that it is not computed several times!
>
> I agree: it can be concurrently computed several times (but a given thread
> would only compute it at most once).
> I'm sory: I read too quickly and didn't understand that you were concerned
> about the computation happening only once for all threads.
>
> > > Since you use a lock I think some clever combination of memoized
> > functions
> > > can create a deadlock.
>
> > No. In the protected area we simply create a promise and fire off a
> > thread, which does the computation. Then we return immediatelly. So no
> > deadlock possibility here. However we trade one lock for the „other“
> > (the promise). What is the possibility of a deadlock here? Well, the
> > computation of f never completes. But this is not a problem of memoize.
> > The only way memoize could cause a problem here is that the computation
> > of f somehow calls f again with the same arguments. Then it would
> > deadlock on the promise, but without memoize we would also have a
> > infinite loop here...
>
> You're right of course. I apologize.
> As a minor note: couldn't a future replace your promise? Or couldn't you get
> rid of the other thread and deliver the promise in the same thread but
> outside of the (locking ..) form?
> Hmm or even a delay!?
>
> Ok I tried to used delays. So I slightly modified my memoize5 (see memoize6)
> and I built on that a memoize7 which enforces (through delays) that a value
> is onlycomputed once (except if the strategy previously removed it from the
> cache of course).
>
> Do you see a problem in my latest 
> implementation?http://gist.github.com/330644#LID153
>
> Thank you,
>
> Christophe

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

Reply via email to