Re: Opinion on core.async vs callbacks in abstract APIs?
I'd like to add that core.async is quite a big thing, it has lots of parts that could be implemented differently. -- 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.
Re: Opinion on core.async vs callbacks in abstract APIs?
I would implement everything sticking to just callbacks, then create separately requirable core.async version of API if that matters. Ideally this should be a separate lib, but practically, it seems better to just have a separate file. понедельник, 1 июня 2015 г., 22:18:19 UTC+3 пользователь Christopher Small написал: Greetings I imagine most of us here would rather use core.async channels over callbacks in their application code, particularly with more complicated applications. But is it okay/preferable for Clojure libraries to force their users to use core.async channels as part of an API (an event channel, for example)? As much as I love core.async, I can't help but wonder whether sticking with callbacks for an API isn't a simpler/better design strategy. It's easy enough to drop messages on a channel in a callback, and this let's users opt-in. But if one expects core.async channels are what most would prefer anyway, is it okay to foist them upon everyone? As a follow up, does your opinion on the matter change if implementations of an API become simpler using core.async channels? Looking forward to your thoughts :-) Chris Small PS I'm asking because I'm working on a physical computing API ( https://github.com/clj-bots/pin-ctrl) and debating between using channels vs callbacks for the edge detection functionality (if you're not familiar, edge detection let's you asynchronously handle changes in pin state, such as button pushes). If you're interested in this question as it applies specifically to this application, feel free to join the discussion on our gitter channel: https://gitter.im/clj-bots/chat -- 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.
Multi-project Set-up
Go to your checked out project and run lein install there. -- 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.
Re: which are the pros and cons between stuartsierra/component and prismatic/graph?
You can have a look at https://github.com/dar-clojure/container and a bit far-fetched example https://gist.github.com/eldargab/77ae221f3cc0a82b76ab. четверг, 5 февраля 2015 г., 21:52:53 UTC+3 пользователь Juan A. Ruz @tangrammer написал: Thanks to all for your good points! Sorry for the delay answering but I needed to review the docs first, now I'll try to be brave and summarise here Graph vs Component features and/or properties ... 1. *graph* and *component* solve dependency injection 2. *component* solves state management (Lifecyle protocol and SystemMap record) 3. *component* comes with reloaded workflow 4. *graph* lets you analyze, change and compose your functional computation 5. *component* forces you to use defrecord Ok, so I'm convinced now that component is great for state management! ... but, *how can you analyze, change and compose the internals (functional computation) of your defrecords???* I mean that component lib is really great for composing your system (and repl development including mocking components!) but forces you to use closed component that others projects can't *easily* extend [1] or change, so for example, which would be the good pattern to follow if you need monitoring/logging your system in *component (*having that defrecord limitation)? what do you think if you *write your components using graph*? So we keep + system composable using component + component composable using graph = example code here https://github.com/milesian/system-examples/blob/318f58383a7a4917c08147c3d0023e5bd5d93af8/src/milesian/graph_example.clj Thanks again! Juan [1] This was my own newbie attempt to extend defrecords tangrammer/defrecord-wrapper https://github.com/tangrammer/defrecord-wrapper , and milesian/aop https://github.com/milesian/aop the component integration one El miércoles, 4 de febrero de 2015, 13:46:33 (UTC+1), Juan A. Ruz @tangrammer escribió: Hi guys! Can anyone give some insight on the features or downsides of choosing component vs graph libs? Or maybe explain the advantages of using defrecords instead of plain fns? thanks in advance! Juan -- 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.
I am looking for Clojure job
Hi, I am looking for job. Detailed resume is here https://docs.google.com/document/d/1Gx0z9Q7kzdCcvW3-XSvdsMe5Oc0PwJZII8swd3xk2mo/?usp=sharing. My github username is eldargab https://github.com/eldargab (Clojure work is mostly under dar-clojure https://github.com/dar-clojure organization). Would appreciate your offerings and help... -- 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.
Clojurians in Mekkah
Are there clojurians in Mekkah these days? We could meet. -- 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.
[ANN] assets - easy and sane way to get ClojureScript app running
Hi, I recently finished hacking on a small project, that helps to build entire web application (with css, images, etc, not just .cljs files), and think it might be useful for others. The suggested workflow is following: 1) Define assets component(s) com/example/app/assets.edn {:dependencies [com/twitter/bootstrap] :css [app.css] :files [icons.png, background.png] :page {:main-ns com/example/app/main :body index.html}} 2) Then, just build it $ lein assets page com/example/app You get an entire single page application ready to be hosted from anywhere in the web. 3) Another options is to start development server $ lein assets server There are some differences with cljsbuild workflow, namely 1. You can use javascript files just like you use .cljs files 2. You specify namespace as a build entry point I'd like to note that this project is a hack. No new features are planned for near future, although bugs will be fixed, dependencies maintained and patches accepted. Despite the fact, that builder was implemented with ease of extension and customization in mind, the way to do it is not documented. Anyway, I hope you'll find it useful. Here are links leiningen plugin - https://github.com/dar-clojure/assets-lein assets.edn spec - https://github.com/dar-clojure/assets -- 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.
Almost purely functional sortable (demo)
Code - https://github.com/dar-clojure/ui/blob/master/examples/sortable/main.cljs Demo - https://dar-clojure.github.io/ui/files/sortable.html You can feed it 1000 items and it's still alive https://dar-clojure.github.io/ui/files/sortable1000.html. What do you think? :) -- 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.
Re: Almost purely functional sortable (demo)
Thanks, for reporting. Fixed FF issues, now it's at least useable. среда, 3 сентября 2014 г., 22:21:17 UTC+4 пользователь Andy Fingerhut написал: On Mac OS X 10.8.5 + Safari 6.1.6, very nice, very slick. On Mac OS X 10.8.5 + Firefox 32.0, very frustrating, and doesn't work like it does on Safari at all. Not sure if that is a known issue or not. Andy On Wed, Sep 3, 2014 at 11:06 AM, Eldar Gabdullin elda...@gmail.com javascript: wrote: Code - https://github.com/dar-clojure/ui/blob/master/examples/sortable/main.cljs Demo - https://dar-clojure.github.io/ui/files/sortable.html You can feed it 1000 items and it's still alive https://dar-clojure.github.io/ui/files/sortable1000.html. What do you think? :) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.com javascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: 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+u...@googlegroups.com javascript:. 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.
Re: Almost purely functional sortable (demo)
It's might be not quite clear, but everything except bangs (!) is a pure data with no state. For example, we have 3 state configurations - initial, captured and dragging. We need to listen a bunch of global events when dragging. When we are done with dragging, we just return an initial state. That's enough to detach all global listeners and do all cleanup... среда, 3 сентября 2014 г., 22:06:56 UTC+4 пользователь Eldar Gabdullin написал: Code - https://github.com/dar-clojure/ui/blob/master/examples/sortable/main.cljs Demo - https://dar-clojure.github.io/ui/files/sortable.html You can feed it 1000 items and it's still alive https://dar-clojure.github.io/ui/files/sortable1000.html. What do you think? :) -- 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.
Re: Almost purely functional sortable (demo)
It turns out lags in FF were due to phantom position animation, turning that off makes it working in FF like in Safary and Chrome. среда, 3 сентября 2014 г., 22:48:43 UTC+4 пользователь Eldar Gabdullin написал: Thanks, for reporting. Fixed FF issues, now it's at least useable. среда, 3 сентября 2014 г., 22:21:17 UTC+4 пользователь Andy Fingerhut написал: On Mac OS X 10.8.5 + Safari 6.1.6, very nice, very slick. On Mac OS X 10.8.5 + Firefox 32.0, very frustrating, and doesn't work like it does on Safari at all. Not sure if that is a known issue or not. Andy On Wed, Sep 3, 2014 at 11:06 AM, Eldar Gabdullin elda...@gmail.com wrote: Code - https://github.com/dar-clojure/ui/blob/master/examples/sortable/main.cljs Demo - https://dar-clojure.github.io/ui/files/sortable.html You can feed it 1000 items and it's still alive https://dar-clojure.github.io/ui/files/sortable1000.html. What do you think? :) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@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+u...@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+u...@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.
Re: Using an atom for a caching map
Something like the following would be fine for me (def cache (atom {})) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (let [v (calc-value k)] (swap! cache assoc k v) v) v))) (let [value (lookup cache k)] ; use value and @cache here ) суббота, 30 августа 2014 г., 9:27:05 UTC+4 пользователь Colin Fleming написал: 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.
Re: Using an atom for a caching map
Snippet you showed before is also not an atomic. If you want strictly to avoid recomputations you need something more elaborate. May be this (def cache (atom {})) (defn unwrap [v] (if-let [a (get v ::atom)] @a v)) (defn compute [cache k] (let [p {::atom (atom nil)} c (swap! cache assoc k p) val (get c k)] (when (identical? val p) (swap! (::atom p) (fn [_] (calc-value k))) (swap! cache assoc k @(::atom p))) (unwrap val))) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (compute cache k) (unwrap v суббота, 30 августа 2014 г., 11:18:51 UTC+4 пользователь Colin Fleming написал: True, but only if you don't mind possibly calculating the value more than once since the update is not atomic. On 30 August 2014 18:31, Eldar Gabdullin elda...@gmail.com javascript: wrote: Something like the following would be fine for me (def cache (atom {})) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (let [v (calc-value k)] (swap! cache assoc k v) v) v))) (let [value (lookup cache k)] ; use value and @cache here ) суббота, 30 августа 2014 г., 9:27:05 UTC+4 пользователь Colin Fleming написал: 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 clo...@googlegroups.com javascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: 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+u...@googlegroups.com javascript:. 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.
Re: Using an atom for a caching map
Oh, forget to wait for value in unwrap. Here is a better version (defn unwrap [v] (if-let [p (get v ::promise)] @p v)) (defn compute [cache k] (let [p {::promise (promise)} c (swap! cache assoc k p) val (get c k)] (when (identical? val p) (let [result (calc-value k)] (deliver (::promise p) result) (swap! cache assoc k result)) (unwrap val (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (compute cache k) (unwrap v суббота, 30 августа 2014 г., 11:54:59 UTC+4 пользователь Eldar Gabdullin написал: Snippet you showed before is also not an atomic. If you want strictly to avoid recomputations you need something more elaborate. May be this (def cache (atom {})) (defn unwrap [v] (if-let [a (get v ::atom)] @a v)) (defn compute [cache k] (let [p {::atom (atom nil)} c (swap! cache assoc k p) val (get c k)] (when (identical? val p) (swap! (::atom p) (fn [_] (calc-value k))) (swap! cache assoc k @(::atom p))) (unwrap val))) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (compute cache k) (unwrap v суббота, 30 августа 2014 г., 11:18:51 UTC+4 пользователь Colin Fleming написал: True, but only if you don't mind possibly calculating the value more than once since the update is not atomic. On 30 August 2014 18:31, Eldar Gabdullin elda...@gmail.com wrote: Something like the following would be fine for me (def cache (atom {})) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (let [v (calc-value k)] (swap! cache assoc k v) v) v))) (let [value (lookup cache k)] ; use value and @cache here ) суббота, 30 августа 2014 г., 9:27:05 UTC+4 пользователь Colin Fleming написал: 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 clo...@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+u...@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+u...@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.
Re: Using an atom for a caching map
I see... Just in case, I'd like to point out one possible deficiency in your original snippet. Generally, it should be better move value calculation outside of swap call, thus reducing a chance of contention, especially when you have many threads asking for different keys. суббота, 30 августа 2014 г., 14:09:42 UTC+4 пользователь Colin Fleming написал: Yes, in my case the update is atomic but doesn't strictly avoid recomputation (since the Atom can call the calculation function many times). I've given this some hammock time and I don't think that's a problem. However on further investigation I do have to ensure that for each of my keys the value that is returned is identical since it uses identity equality semantics, so I might have to stick with my original solution. Thanks for the input though, it's very interesting to see your solution. On 30 August 2014 19:54, Eldar Gabdullin elda...@gmail.com javascript: wrote: Snippet you showed before is also not an atomic. If you want strictly to avoid recomputations you need something more elaborate. May be this (def cache (atom {})) (defn unwrap [v] (if-let [a (get v ::atom)] @a v)) (defn compute [cache k] (let [p {::atom (atom nil)} c (swap! cache assoc k p) val (get c k)] (when (identical? val p) (swap! (::atom p) (fn [_] (calc-value k))) (swap! cache assoc k @(::atom p))) (unwrap val))) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (compute cache k) (unwrap v суббота, 30 августа 2014 г., 11:18:51 UTC+4 пользователь Colin Fleming написал: True, but only if you don't mind possibly calculating the value more than once since the update is not atomic. On 30 August 2014 18:31, Eldar Gabdullin elda...@gmail.com wrote: Something like the following would be fine for me (def cache (atom {})) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (let [v (calc-value k)] (swap! cache assoc k v) v) v))) (let [value (lookup cache k)] ; use value and @cache here ) суббота, 30 августа 2014 г., 9:27:05 UTC+4 пользователь Colin Fleming написал: 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 clo...@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+u...@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+u...@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 clo...@googlegroups.com javascript: Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+u...@googlegroups.com javascript: 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+u...@googlegroups.com javascript:. 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
Re: Using an atom for a caching map
You are absolutely right. Sorry, for distraction. Deleted my message immediately after I realized that, but it turns out it managed to go already. суббота, 30 августа 2014 г., 16:25:21 UTC+4 пользователь Colin Fleming написал: I'm not sure I understand - the contention will be the same whether or not the value is calculated in the swap! call, right? And if I calculate the value and then pass the calculated value to swap!, that value will be thrown away every time the cache contains an existing value for my key. On 30 August 2014 23:13, Eldar Gabdullin elda...@gmail.com javascript: wrote: I see... Just in case, I'd like to point out one possible deficiency in your original snippet. Generally, it should be better move value calculation outside of swap call, thus reducing a chance of contention, especially when you have many threads asking for different keys. суббота, 30 августа 2014 г., 14:09:42 UTC+4 пользователь Colin Fleming написал: Yes, in my case the update is atomic but doesn't strictly avoid recomputation (since the Atom can call the calculation function many times). I've given this some hammock time and I don't think that's a problem. However on further investigation I do have to ensure that for each of my keys the value that is returned is identical since it uses identity equality semantics, so I might have to stick with my original solution. Thanks for the input though, it's very interesting to see your solution. On 30 August 2014 19:54, Eldar Gabdullin elda...@gmail.com wrote: Snippet you showed before is also not an atomic. If you want strictly to avoid recomputations you need something more elaborate. May be this (def cache (atom {})) (defn unwrap [v] (if-let [a (get v ::atom)] @a v)) (defn compute [cache k] (let [p {::atom (atom nil)} c (swap! cache assoc k p) val (get c k)] (when (identical? val p) (swap! (::atom p) (fn [_] (calc-value k))) (swap! cache assoc k @(::atom p))) (unwrap val))) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (compute cache k) (unwrap v суббота, 30 августа 2014 г., 11:18:51 UTC+4 пользователь Colin Fleming написал: True, but only if you don't mind possibly calculating the value more than once since the update is not atomic. On 30 August 2014 18:31, Eldar Gabdullin elda...@gmail.com wrote: Something like the following would be fine for me (def cache (atom {})) (defn lookup [cache k] (let [v (get @cache k ::nil)] (if (= v ::nil) (let [v (calc-value k)] (swap! cache assoc k v) v) v))) (let [value (lookup cache k)] ; use value and @cache here ) суббота, 30 августа 2014 г., 9:27:05 UTC+4 пользователь Colin Fleming написал: 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 clo...@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+u...@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+u...@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 clo...@googlegroups.com Note that posts from new members are moderated - please be patient with your first post