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
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 eldar...@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 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.
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
On 30 August 2014 06:26, Colin Fleming colin.mailingl...@gmail.com wrote: 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 ...) Why not just use memoize? (def calc-value (memoize (fn [key] ...)) If you need more control over the cache, check out core.memoize (which builds on top of core.cache). Ray. -- 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: How can I add meta to an object that doesn't implement IObj?
On 30/08/14 05:15, Atamert Ölçgen wrote: Obviously I can't. But I need to add this capability to an object. During testing I attach meta to this object that contains an atom. Then I pass this object to other functions, known in runtime. I can't use a dynamic var because all this happens within a mock function that may be retried and run in different threads. In my case I used a list, e.g. (list obj), and used destructuring on the other side when needed, e.g. [obj :as wobj]. I have seen this: http://stackoverflow.com/questions/20724219/simplest-possible-clojure-object-that-can-accept-a-primitive-and-metadata but can't deref it since I can't change the functions that will use it later. If I wrap this object I need to be able to delegate all of its functionality to the original object. I don't think there's a quick solution without changing the contract. Whatever solution is chosen you need to keep in mind how this will affect things like equality, hashing, and instanceof? Perhaps these links could be a start: https://groups.google.com/forum/#!topic/clojure/9zCGdW_Q7o8 https://groups.google.com/forum/#%21topic/clojure/9zCGdW_Q7o8 http://stackoverflow.com/questions/9086926/create-a-proxy-for-an-specific-instance-of-an-object-in-clojure Also, if the meta data is just for you own use, then you might want to store it yourself in a map with weak references, or just use WeakHashMap http://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html directly. But then you'll be stateful... -- 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: How can I add meta to an object that doesn't implement IObj?
Hi François, Thanks for the links. I can't really pass a list since the first function is expecting the object I am passing, then it calls some other functions that were supposed to extract the meta. The problem is, functions that are called later can be executed in a different thread. On Sat, Aug 30, 2014 at 4:29 PM, François Rey fmj...@gmail.com wrote: On 30/08/14 05:15, Atamert Ölçgen wrote: Obviously I can't. But I need to add this capability to an object. During testing I attach meta to this object that contains an atom. Then I pass this object to other functions, known in runtime. I can't use a dynamic var because all this happens within a mock function that may be retried and run in different threads. In my case I used a list, e.g. (list obj), and used destructuring on the other side when needed, e.g. [obj :as wobj]. I have seen this: http://stackoverflow.com/questions/20724219/simplest-possible-clojure-object-that-can-accept-a-primitive-and-metadata but can't deref it since I can't change the functions that will use it later. If I wrap this object I need to be able to delegate all of its functionality to the original object. I don't think there's a quick solution without changing the contract. Whatever solution is chosen you need to keep in mind how this will affect things like equality, hashing, and instanceof? Perhaps these links could be a start: https://groups.google.com/forum/#!topic/clojure/9zCGdW_Q7o8 http://stackoverflow.com/questions/9086926/create-a-proxy-for-an-specific-instance-of-an-object-in-clojure Also, if the meta data is just for you own use, then you might want to store it yourself in a map with weak references, or just use WeakHashMap http://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html directly. But then you'll be stateful... -- 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. -- Kind Regards, Atamert Ölçgen -+- --+ +++ www.muhuk.com -- 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: How can I add meta to an object that doesn't implement IObj?
The only way to do this is to wrap the object in something that implements IObj. But at that point you might as well wrap it in a regular hashmap and just wrap it in real data. On Sat, Aug 30, 2014 at 1:54 AM, Atamert Ölçgen mu...@muhuk.com wrote: Hi François, Thanks for the links. I can't really pass a list since the first function is expecting the object I am passing, then it calls some other functions that were supposed to extract the meta. The problem is, functions that are called later can be executed in a different thread. On Sat, Aug 30, 2014 at 4:29 PM, François Rey fmj...@gmail.com wrote: On 30/08/14 05:15, Atamert Ölçgen wrote: Obviously I can't. But I need to add this capability to an object. During testing I attach meta to this object that contains an atom. Then I pass this object to other functions, known in runtime. I can't use a dynamic var because all this happens within a mock function that may be retried and run in different threads. In my case I used a list, e.g. (list obj), and used destructuring on the other side when needed, e.g. [obj :as wobj]. I have seen this: http://stackoverflow.com/questions/20724219/simplest-possible-clojure-object-that-can-accept-a-primitive-and-metadata but can't deref it since I can't change the functions that will use it later. If I wrap this object I need to be able to delegate all of its functionality to the original object. I don't think there's a quick solution without changing the contract. Whatever solution is chosen you need to keep in mind how this will affect things like equality, hashing, and instanceof? Perhaps these links could be a start: https://groups.google.com/forum/#!topic/clojure/9zCGdW_Q7o8 http://stackoverflow.com/questions/9086926/create-a-proxy-for-an-specific-instance-of-an-object-in-clojure Also, if the meta data is just for you own use, then you might want to store it yourself in a map with weak references, or just use WeakHashMap http://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html directly. But then you'll be stateful... -- 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. -- Kind Regards, Atamert Ölçgen -+- --+ +++ www.muhuk.com -- 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.
Re: Using an atom for a caching map
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 eldar...@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 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
Re: Using an atom for a caching map
In my case I can't use memoize because I need to supply the cache map - that in turn is stored on another object so it can be invalidated by events outside my control. On 30 August 2014 20:00, Ray Miller r...@1729.org.uk wrote: On 30 August 2014 06:26, Colin Fleming colin.mailingl...@gmail.com wrote: 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 ...) Why not just use memoize? (def calc-value (memoize (fn [key] ...)) If you need more control over the cache, check out core.memoize (which builds on top of core.cache). Ray. -- 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.
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: How can I add meta to an object that doesn't implement IObj?
It would probably help if you said more about the source of this atom-holding object. Is it a plain Java class? A deftype/defrecord? Is it final? If you can control the construction of this object and its class is not final, you can subclass it and add an IObj implementation. (Note that most, maybe all clojure ways of creating classes create final classes, so this technique won't work.) The easiest way to subclass is with `proxy`: (defn meta-AtomHolder [atom-value metadata] (proxy [AtomHolderClass clojure.lang.IObj] ;; [superclass, new interfaces] [atom-value] ;; constructor args (meta [] metadata) ;; subclass method (withMeta [newmeta] (meta-AtomHolder newmeta = (var user/meta-AtomHolder) (meta-AtomHolder (atom x) {}) = #AtomHolderClass$IObj$40298964 user.proxy$AtomHolderClass$IObj$40298964@302c28cc (meta (meta-AtomHolder (atom x) {})) = {} (meta (with-meta (meta-AtomHolder (atom x) {}) {:a 1})) = {:a 1} If the parent class is final or you can't construct the object yourself, you need to delegate method calls from one instance to this object instance. I think this is hard-but-not-impossible in java, but I'm not sure. (Clojurescript has `specify`, which does exactly what you want, but only exists because delegation between instances in javascript is trivial.) On Friday, August 29, 2014 10:16:05 PM UTC-5, Atamert Ölçgen wrote: Obviously I can't. But I need to add this capability to an object. During testing I attach meta to this object that contains an atom. Then I pass this object to other functions, known in runtime. I can't use a dynamic var because all this happens within a mock function that may be retried and run in different threads. I have seen this: http://stackoverflow.com/questions/20724219/simplest-possible-clojure-object-that-can-accept-a-primitive-and-metadata but can't deref it since I can't change the functions that will use it later. If I wrap this object I need to be able to delegate all of its functionality to the original object. I hope this all is not too vague. The code I'm working on is not online yet. But it's for clecs (https://github.com/muhuk/clecs/), I'm adding quickcheck to compare different world implementations. -- Kind Regards, Atamert Ölçgen -+- --+ +++ www.muhuk.com -- 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: Why is this an Exception ?
On Saturday, August 30, 2014 12:34:24 AM UTC+5:30, Ashton Kemerling wrote: Bar/baz refers to the symbol baz in the namespace bar. If you haven't created and imported bar, that's an error. This feels too java-ish for a lisp. Can I avoid this by some form of declaration ? -- 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'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 eldar...@gmail.com 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. 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,
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.
Re: How can I add meta to an object that doesn't implement IObj?
Can you monkey-patch the meta function itself to draw from a map of object to meta? On Saturday, August 30, 2014, Francis Avila franci...@gmail.com wrote: It would probably help if you said more about the source of this atom-holding object. Is it a plain Java class? A deftype/defrecord? Is it final? If you can control the construction of this object and its class is not final, you can subclass it and add an IObj implementation. (Note that most, maybe all clojure ways of creating classes create final classes, so this technique won't work.) The easiest way to subclass is with `proxy`: (defn meta-AtomHolder [atom-value metadata] (proxy [AtomHolderClass clojure.lang.IObj] ;; [superclass, new interfaces] [atom-value] ;; constructor args (meta [] metadata) ;; subclass method (withMeta [newmeta] (meta-AtomHolder newmeta = (var user/meta-AtomHolder) (meta-AtomHolder (atom x) {}) = #AtomHolderClass$IObj$40298964 user.proxy$AtomHolderClass$IObj$40298964@302c28cc (meta (meta-AtomHolder (atom x) {})) = {} (meta (with-meta (meta-AtomHolder (atom x) {}) {:a 1})) = {:a 1} If the parent class is final or you can't construct the object yourself, you need to delegate method calls from one instance to this object instance. I think this is hard-but-not-impossible in java, but I'm not sure. (Clojurescript has `specify`, which does exactly what you want, but only exists because delegation between instances in javascript is trivial.) On Friday, August 29, 2014 10:16:05 PM UTC-5, Atamert Ölçgen wrote: Obviously I can't. But I need to add this capability to an object. During testing I attach meta to this object that contains an atom. Then I pass this object to other functions, known in runtime. I can't use a dynamic var because all this happens within a mock function that may be retried and run in different threads. I have seen this: http://stackoverflow.com/questions/20724219/ simplest-possible-clojure-object-that-can-accept-a-primitive-and-metadata but can't deref it since I can't change the functions that will use it later. If I wrap this object I need to be able to delegate all of its functionality to the original object. I hope this all is not too vague. The code I'm working on is not online yet. But it's for clecs (https://github.com/muhuk/clecs/), I'm adding quickcheck to compare different world implementations. -- Kind Regards, Atamert Ölçgen -+- --+ +++ www.muhuk.com -- 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 javascript:_e(%7B%7D,'cvml','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 javascript:_e(%7B%7D,'cvml','clojure%2bunsubscr...@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 javascript:_e(%7B%7D,'cvml','clojure%2bunsubscr...@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.
Puzzling list comp error: Don't know how to create ISeq from: clojure.lang.Keyword
I have a long function which produces `list-of-lists` : ((Sun 21 li 13 201.2139410) (Moon 11 le 21 131.3457459) ..) before entering a list comprehension (simplified for brevity): (defn calc ... (let [ . ... list-of-lists (map #(rest (first %)) results)] (for [l list-of-lists plan (keyword (first l)) deg (Integer/parseInt (second l)) sign (signs (keyword (first (rest (rest l) min (Integer/parseInt (second (rest (rest l long (Float/parseFloat (last l))] {:deg deg :min min :long long}))) When I call the function I get this error: IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:505) I've tested all the bindings in the repl and they produce the desired data so it seems the final construction of the map is where the problem lies. gvim -- 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: Puzzling list comp error: Don't know how to create ISeq from: clojure.lang.Keyword
for macro expects each pair to be either binding-form/collection-expr or one of known modifiers (:let, :when, :while). Here: plan (keyword (first l)) you give a pair of binding-form and keyword (which is really impossible to iterate over). If you meant let-binding for plan, dec, min and long, use :let modifier (you can find example in documentation - http://clojuredocs.org/clojure_core/clojure.core/for). 2014-08-30 16:47 GMT+03:00 gvim gvi...@gmail.com: I have a long function which produces `list-of-lists` : ((Sun 21 li 13 201.2139410) (Moon 11 le 21 131.3457459) ..) before entering a list comprehension (simplified for brevity): (defn calc ... (let [ . ... list-of-lists (map #(rest (first %)) results)] (for [l list-of-lists plan (keyword (first l)) deg (Integer/parseInt (second l)) sign (signs (keyword (first (rest (rest l) min (Integer/parseInt (second (rest (rest l long (Float/parseFloat (last l))] {:deg deg :min min :long long}))) When I call the function I get this error: IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:505) I've tested all the bindings in the repl and they produce the desired data so it seems the final construction of the map is where the problem lies. gvim -- 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. -- Kind regards, Alexey S. Kachayev, CTO at Attendify.com -- http://github.com/kachayev http://twitter.com/kachayev Skype: kachayev Tel: +380-996692092 -- 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: Puzzling list comp error: Don't know how to create ISeq from: clojure.lang.Keyword
On 30/08/2014 15:07, Alexey Kachayev wrote: for macro expects each pair to be either binding-form/collection-expr or one of known modifiers (:let, :when, :while). Here: plan (keyword (first l)) you give a pair of binding-form and keyword (which is really impossible to iterate over). If you meant let-binding for plan, dec, min and long, use :let modifier (you can find example in documentation - http://clojuredocs.org/clojure_core/clojure.core/for). Yes, of course :) I confused list comp bindings with let bindings. Thanks. gvim -- 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: Puzzling list comp error: Don't know how to create ISeq from: clojure.lang.Keyword
On 30/08/2014 15:07, Alexey Kachayev wrote: for macro expects each pair to be either binding-form/collection-expr or one of known modifiers (:let, :when, :while). Here: plan (keyword (first l)) you give a pair of binding-form and keyword (which is really impossible to iterate over). If you meant let-binding for plan, dec, min and long, use :let modifier (you can find example in documentation - http://clojuredocs.org/clojure_core/clojure.core/for). I'm going to have to reduce the resulting list next so I thought to use a map version of the list comp. but ran into a similar error: (defn calc ... (let [ . ... list-of-lists (map #(rest (first %)) results)] (- list-of-lists (map #(let [plan (keyword (first %)) deg (Integer/parseInt (second %)) sign (signs (keyword (first (rest (rest %) min (Integer/parseInt (second (rest (rest % long (Float/parseFloat (last %))] {plan {:sign sign :deg deg :min min :long long}}))) Don't know how to create ISeq from: astro.calc$calc$fn__29869 Now I'm using a let form but the error is similar. gvim 2014-08-30 16:47 GMT+03:00 gvim gvi...@gmail.com mailto:gvi...@gmail.com: I have a long function which produces `list-of-lists` : ((Sun 21 li 13 201.2139410 tel:201.2139410) (Moon 11 le 21 131.3457459) ..) before entering a list comprehension (simplified for brevity): (defn calc ... (let [ . ... list-of-lists (map #(rest (first %)) results)] (for [l list-of-lists plan (keyword (first l)) deg (Integer/parseInt (second l)) sign (signs (keyword (first (rest (rest l) min (Integer/parseInt (second (rest (rest l long (Float/parseFloat (last l))] {:deg deg :min min :long long}))) When I call the function I get this error: IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:505) I've tested all the bindings in the repl and they produce the desired data so it seems the final construction of the map is where the problem lies. gvim -- 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 mailto: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+unsubscribe@__googlegroups.com mailto:clojure%2bunsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/__group/clojure?hl=en 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+unsubscribe@__googlegroups.com mailto:clojure%2bunsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/__optout https://groups.google.com/d/optout. -- Kind regards, Alexey S. Kachayev, CTO at Attendify.com -- http://github.com/kachayev http://twitter.com/kachayev Skype: kachayev Tel: +380-996692092 -- 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 mailto: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.
Re: Puzzling list comp error: Don't know how to create ISeq from: clojure.lang.Keyword
Thread-first macro - will insert list-of-lists as first argument for map, which is definitely not what you expect. Use threading-last - instead. 2014-08-30 18:48 GMT+03:00 gvim gvi...@gmail.com: On 30/08/2014 15:07, Alexey Kachayev wrote: for macro expects each pair to be either binding-form/collection-expr or one of known modifiers (:let, :when, :while). Here: plan (keyword (first l)) you give a pair of binding-form and keyword (which is really impossible to iterate over). If you meant let-binding for plan, dec, min and long, use :let modifier (you can find example in documentation - http://clojuredocs.org/clojure_core/clojure.core/for). I'm going to have to reduce the resulting list next so I thought to use a map version of the list comp. but ran into a similar error: (defn calc ... (let [ . ... list-of-lists (map #(rest (first %)) results)] (- list-of-lists (map #(let [plan (keyword (first %)) deg (Integer/parseInt (second %)) sign (signs (keyword (first (rest (rest %) min (Integer/parseInt (second (rest (rest % long (Float/parseFloat (last %))] {plan {:sign sign :deg deg :min min :long long}}))) Don't know how to create ISeq from: astro.calc$calc$fn__29869 Now I'm using a let form but the error is similar. gvim 2014-08-30 16:47 GMT+03:00 gvim gvi...@gmail.com mailto:gvi...@gmail.com: I have a long function which produces `list-of-lists` : ((Sun 21 li 13 201.2139410 tel:201.2139410) (Moon 11 le 21 131.3457459) ..) before entering a list comprehension (simplified for brevity): (defn calc ... (let [ . ... list-of-lists (map #(rest (first %)) results)] (for [l list-of-lists plan (keyword (first l)) deg (Integer/parseInt (second l)) sign (signs (keyword (first (rest (rest l) min (Integer/parseInt (second (rest (rest l long (Float/parseFloat (last l))] {:deg deg :min min :long long}))) When I call the function I get this error: IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:505) I've tested all the bindings in the repl and they produce the desired data so it seems the final construction of the map is where the problem lies. gvim -- 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 mailto: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+unsubscribe@__googlegroups.com mailto:clojure%2bunsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/__group/clojure?hl=en 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+unsubscribe@__googlegroups.com mailto:clojure%2bunsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/__optout https://groups.google.com/d/optout. -- Kind regards, Alexey S. Kachayev, CTO at Attendify.com -- http://github.com/kachayev http://twitter.com/kachayev Skype: kachayev Tel: +380-996692092 -- 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 mailto: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
Re: Puzzling list comp error: Don't know how to create ISeq from: clojure.lang.Keyword
On 30/08/2014 17:04, Alexey Kachayev wrote: Thread-first macro -will insert list-of-listsas first argument for map, which is definitely not what you expect. Use threading-last -instead. I've never quite understood the distinction other than - does everything top to bottom and - does the reverse. From what you're saying the choice also affects which position the argument is inserted? If so this presents a complication in that threading through several functions may require the argument to be inserted in different positions? gvim -- 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 must be missing something, because this is too simple? (defn get-maybe-cached [cache key] (dosync (if-let [v (get @cache key)] v (do (reset! cache (assoc @cache key (calculate key))) (get @cache key) On Saturday, August 30, 2014 3:27:05 PM UTC+10, 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.
Re: Using an atom for a caching map
How about something like this? You can still keep your cache as an atom that you can pass around, and you avoid unnecessary recomputation through memoize: (def cache (atom {})) (def lookup (let [calc-value* (memoize calc-value)] (fn [cache k] (when-not (contains? @cache k) (swap! cache assoc k (calc-value* k))) (@cache k Den lördagen den 30:e augusti 2014 kl. 12:11:58 UTC+2 skrev Colin Fleming: In my case I can't use memoize because I need to supply the cache map - that in turn is stored on another object so it can be invalidated by events outside my control. On 30 August 2014 20:00, Ray Miller r...@1729.org.uk javascript: wrote: On 30 August 2014 06:26, Colin Fleming colin.ma...@gmail.com javascript: wrote: 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 ...) Why not just use memoize? (def calc-value (memoize (fn [key] ...)) If you need more control over the cache, check out core.memoize (which builds on top of core.cache). Ray. -- 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: Why is this an Exception ?
How would another Lisp avoid giving you an error when referring to a symbol that has no value? If you just want your entire program in a single namespace, and don't want to use any libraries in other namespaces, then simply don't use the / character in your symbol names. If you want to use the symbols in other namespaces without a namespace/ prefix in front of them, you can use a declaration like this: (ns my.namespace.name (:require [other.namespace :refer :all] [yet.another.namespace :refer :all])) Then you can use the names of public symbols from other.namespace and yet.another.namespace in your code without the namespace prefix. Andy On Sat, Aug 30, 2014 at 1:02 AM, Sreeharsha Mudivarti msreehar...@gmail.com wrote: On Saturday, August 30, 2014 12:34:24 AM UTC+5:30, Ashton Kemerling wrote: Bar/baz refers to the symbol baz in the namespace bar. If you haven't created and imported bar, that's an error. This feels too java-ish for a lisp. Can I avoid this by some form of declaration ? -- 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.
Re: Puzzling list comp error: Don't know how to create ISeq from: clojure.lang.Keyword
`-` inserts its first argument into the second position of the next argument, and so on, so (- [] (conj 1) (conj 2)) Turns into (conj (conj [] 1) 2) `-` inserts its first argument into the LAST position of the next argument, and so on, so (- 1 (conj [2]) (conj [3])) Turns into (conj [3] (conj [2] 1)) I guess it is bottom to top, in a way, but I always thought that was kind of an artifact of the argument (re-)ordering. On Saturday, August 30, 2014 12:19:31 PM UTC-4, g vim wrote: On 30/08/2014 17:04, Alexey Kachayev wrote: Thread-first macro -will insert list-of-listsas first argument for map, which is definitely not what you expect. Use threading-last -instead. I've never quite understood the distinction other than - does everything top to bottom and - does the reverse. From what you're saying the choice also affects which position the argument is inserted? If so this presents a complication in that threading through several functions may require the argument to be inserted in different positions? gvim -- 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: Resources for intermediate/not-absolute-beginner Clojurians
+1 for JOC. It's a fantastic book. Chris On Friday, August 29, 2014 6:28:25 PM UTC-7, Paul L. Snyder wrote: On Fri, 29 Aug 2014, Sam Raker wrote: I'm just not sure what to do at this point in my Clojure learning experience. I've probably written a few thousand lines of Clojure at this point, but I'm not sure that I'm doing things right: I don't know if my code is efficient, or even idiomatic. I've know next to nothing about Java, and Clojure is my first introduction to functional programming. There are so many fun, exciting, awesome-seeming things in Clojure that I want to take advantage of, like reference types and futures, but I have no point of reference for them and feel like I'm having trouble wrapping my head around them. It sounds like you're at the perfect moment to hit up _The Joy of Clojure_. The second edition came out recently, so it should be nicely current. My copy of 2e is on my in-pile, so I can't yet comment specifically on the updates, but its approach is aimed directly at what you seem to be looking for: why Clojure is Clojure, and what you can do about it. http://joyofclojure.com/ Paul -- 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: Resources for intermediate/not-absolute-beginner Clojurians
Eventually you'll have to come around to reading implementations. The Joy of Clojure is a very thoughtful book, but lib authors aren't going to go through the same amount of trouble. Reading code gets easier and rewards faster the more you do it. On Saturday, August 30, 2014, Christopher Small metasoar...@gmail.com wrote: +1 for JOC. It's a fantastic book. Chris On Friday, August 29, 2014 6:28:25 PM UTC-7, Paul L. Snyder wrote: On Fri, 29 Aug 2014, Sam Raker wrote: I'm just not sure what to do at this point in my Clojure learning experience. I've probably written a few thousand lines of Clojure at this point, but I'm not sure that I'm doing things right: I don't know if my code is efficient, or even idiomatic. I've know next to nothing about Java, and Clojure is my first introduction to functional programming. There are so many fun, exciting, awesome-seeming things in Clojure that I want to take advantage of, like reference types and futures, but I have no point of reference for them and feel like I'm having trouble wrapping my head around them. It sounds like you're at the perfect moment to hit up _The Joy of Clojure_. The second edition came out recently, so it should be nicely current. My copy of 2e is on my in-pile, so I can't yet comment specifically on the updates, but its approach is aimed directly at what you seem to be looking for: why Clojure is Clojure, and what you can do about it. http://joyofclojure.com/ Paul -- 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 javascript:_e(%7B%7D,'cvml','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 javascript:_e(%7B%7D,'cvml','clojure%2bunsubscr...@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 javascript:_e(%7B%7D,'cvml','clojure%2bunsubscr...@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: Resources for intermediate/not-absolute-beginner Clojurians
Hi Sam, I am working on a book for Pragmatic Programmers with Ben Vandgrift called Clojure Applied that is target specifically at people like yourself. Our goal is to bridge the gap between knowing the syntax and basics of the language to knowing how to apply it in building applications. The first half of the book is in tech review now and it will likely be a beta book in October or November with final release in early 2015. I would also certainly encourage you to read code and understand the libraries you use (or Clojure itself) at a deeper level! Alex On Friday, August 29, 2014 7:14:36 PM UTC-5, Sam Raker wrote: I worked my way through *Clojure Programming* (Emerick, Carper, Grand, O'Reilly), and I've started writing my own Clojure (porting over an unfinished Python project that seemed amenable to the Clojure treatment.) I really love the language, but I'm not sure where to go from here. My other main language is Python, which I learned in school, and also found a bunch of intermediate/non-introductory resources for, like the awesome, short, topic-oriented monographs (for lack of a better term) by Matt Harrison (e.g., http://www.amazon.com/Guide-Learning-Iteration-Generators-Python-ebook/dp/B007JR4FCQ/ref=sr_1_3). These really helped me understand some of the less-obvious/less-intro parts of Python, and the stuff I learned in school helped me learn what idiomatic Python looked/felt like. I'm just not sure what to do at this point in my Clojure learning experience. I've probably written a few thousand lines of Clojure at this point, but I'm not sure that I'm doing things right: I don't know if my code is efficient, or even idiomatic. I've know next to nothing about Java, and Clojure is my first introduction to functional programming. There are so many fun, exciting, awesome-seeming things in Clojure that I want to take advantage of, like reference types and futures, but I have no point of reference for them and feel like I'm having trouble wrapping my head around them. I've come to realize that I learn best from books, and while code literacy is something I need to work on, read the sourcecode [for library X] isn't going to help me that much, unless it's aggressively commented/documented. I don't really want another intro book, since I'd rather not pay for too much overlap, and while I'll happily accept recommendations for application-/domain-specific books, I'm more looking for a deeper dive into the language itself. I'm being really difficult about this, and I'm sorry in advance. Any and all suggestions are welcome. Thanks guys! -- 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.