Re: Opinion on core.async vs callbacks in abstract APIs?

2015-06-01 Thread Eldar Gabdullin
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?

2015-06-01 Thread Eldar Gabdullin
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

2015-02-26 Thread Eldar Gabdullin
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?

2015-02-06 Thread Eldar Gabdullin
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

2014-10-16 Thread Eldar Gabdullin
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

2014-09-27 Thread Eldar Gabdullin
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

2014-09-16 Thread Eldar Gabdullin
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)

2014-09-03 Thread 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)

2014-09-03 Thread 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 
 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)

2014-09-03 Thread Eldar Gabdullin
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)

2014-09-03 Thread Eldar Gabdullin
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

2014-08-30 Thread Eldar Gabdullin
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

2014-08-30 Thread 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 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

2014-08-30 Thread Eldar Gabdullin
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

2014-08-30 Thread Eldar Gabdullin
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

2014-08-30 Thread Eldar Gabdullin
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