Passing data out of closure into the outer context

53 views
Skip to first unread message

Tom Krestle

unread,
Mar 20, 2012, 11:16:22 AM3/20/12
to clo...@googlegroups.com
Greetings,

I've stumbled across the following problem, which I believe is common and should have some sort of generic solution. Imagine I have

... ;; code inside defn
;; I extract some information out of my atom in closure:
(swap! my-atom 
  (fn [val] 
    (let [extracted-info1 (extract-something-from val) 
      extracted-info2 (extract-something-else-from val)] 
        ;; update the atom
        (-> val
          (assoc ...) (assoc))))) ;; out of swap!

;; still code inside defn
;; now, here I need to use those extracted-info1, extracted-info2 that I got out of atom inside swap! operation
;; What would be the common way to pass that information here? Using vals doesn't sound right.

Have a beer!
Tom

Cedric Greevey

unread,
Mar 20, 2012, 5:13:18 PM3/20/12
to clo...@googlegroups.com

The ugly way, as you noted, is to change the atom from some-map to
[some-map extracted-info-from-last-swap].

A less ugly way might be

(let [ei (atom nil)]
(swap! my-atom
...
(reset! ei extracted-info1)
...)
(do-things-with ei))

If the swap! is retried, the ei atom will be reset! more than once,
but it will after the swap! contain the extracted-info1 from the
successful swap! of my-atom.

The most functional way would be to see if you couldn't do the work
with ei *inside* the closure. However, if it's expensive or
side-effecty that doesn't play nice with swap! retrying. In that
instance, you might want to think of replacing my-atom with my-ref and
doing something like

(dosync
(alter my-ref
...
(send-off ei-agent ei-do-things-func extracted-info1)
...))

Agent sends are held until a transaction commits, so the
ei-do-things-func will be called only once for each transaction on
my-ref.

Tom Krestle

unread,
Mar 21, 2012, 10:26:05 AM3/21/12
to clo...@googlegroups.com

Thanks, man! I ended up using atoms.
Reply all
Reply to author
Forward
0 new messages