I believe you can replace:
(when-not (contains? @cache k)
  (swap! cache assoc k (calc-value* k))))

with:
(swap! cache (fn [cache']
               (if (contains? cache' k)
                 cache'
                 (assoc cache' k (calc-value* k)))))

Note: I haven't run this code


On Mon, Sep 1, 2014 at 2:20 AM, Colin Fleming <colin.mailingl...@gmail.com>
wrote:

> Hi Thomas,
>
> Normally I'd agree with you, but in my case it actually works quite well
> since I don't need to expire or worry about sizing. This is for caching
> objects on IntelliJ parse tree elements, and the element with its cached
> values is thrown away every time the document is parsed, so these are
> pretty transient caches. In this particular case the calculation isn't too
> heavyweight either so recalculating it in the unlikely event of contention
> isn't a big deal. In fact, this discussion and the related thinking has
> made me realise that my original solution was actually sufficient for my
> somewhat strange use case, which is nice :-). For more typical server side
> caching, I agree that Guava would be a great solution.
>
> Cheers,
> Colin
>
>
> On 1 September 2014 20:54, Thomas Heller <th.hel...@gmail.com> wrote:
>
>> As much as I like Clojure and atoms, I do not think they are a good fit
>> for caching. Not only is it impossible to address the concurrency issues
>> related to multiple threads loading the same object, but you also have to
>> do expiration and size management yourself. Immutability doesn't help much
>> for caching either. There is core.cache that does some bits but I probably
>> would recommend using something like CacheBuilder from the guava libs:
>>
>> See
>> https://code.google.com/p/guava-libraries/
>>
>> http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/cache/CacheBuilder.html
>>
>> Its Java but the Clojure<->Java interop is so good that it doesn't matter
>> much.
>>
>> On Saturday, August 30, 2014 7:27:05 AM UTC+2, Colin Fleming wrote:
>>>
>>> Hi all,
>>>
>>> I want to use a map to cache values based on a key. I'm planning to use
>>> an atom for this. My basic operation is "give me the value for this key" -
>>> if the value exists in the map then that value should be returned,
>>> otherwise a new value should be calculated, inserted in the map and then
>>> returned. My plan is to implement something like the following:
>>>
>>>
>>> (defn ensure [cache key]  (if (contains? cache key)    cache    (assoc 
>>> cache key (calc-value key))))(let [value (get (swap! cache ensure key) 
>>> key)]  ... do my thing with value ...)
>>>
>>>
>>> So 'ensure' ensures that the cache contains the value for key, the swap!
>>> operation returns the cache with the value and then I get it out. This
>>> works but feels a little clumsy, is there a better way to do this?
>>>
>>> Also, looking at the Atom source code, I see that this will cause a CAS
>>> operation even if the value returned from swap! is identical to the
>>> original value. It seems like a reasonable optimisation would be to check
>>> if the values are identical and not update if so - is there a reason this
>>> might not be a good idea?
>>>
>>> Thanks,
>>> Colin
>>>
>>  --
>> 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.
>

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