generate-key is not thread-safe. Multiple callers might get the same id. It would probably be worthwhile to have your debit fn disallow a negative balance in some way. Maybe also don't allow closing an account unless it has zero balance. (Though the latter might require coordination between the "bank" and the account ref, hence bank can't be an atom any more.) Do at least consider the case where one thread already has a reference to an account another thread is closing. My latest iteration has brought me to this:
https://github.com/jimpil/bankio/blob/master/src/bankio/core.clj If anyone can think of a more evident and safe approach for demonstration purposes, by all means, shout out. After consulting the Clojure Programming book, I decided to use commute for simply depositing in to an account. There are still 2 fns that use dosync but only modify a single identity, namely deposit! & withdraw!. I don't see how else this can be done since they are refs. I would appreciate feedback for this (hopefully) last version... many thanks in advance :) Jim On 21/11/13 13:19, John D. Hume wrote: If you want to demonstrate STM with the deposit-withdraw-transfer example, you definitely need a ref for each account. I'd suggest an atom for the account-num->balance-ref map ("the bank") and an atom for the account-num-generator, but you say coordination is necessary for opening and closing accounts. What coordination do you have in mind? On Nov 21, 2013 5:27 AM, "Jim - FooBar();" <jimpil1...@gmail.com> wrote: > also I forgot to add that having the bank in some reference type allows > opening/closing new accounts, an operation that at least to me sounds like > it needs coordination... > So which way is preferred? map-ref that stores values, map that stores > refs or map-ref that stores refs? > > Jim > > > On 21/11/13 10:58, Jim - FooBar(); wrote: > >> Hi Stefan, >> >> thanks for your interest. let me explain further... >> >> 1. I did start with a design that involved a map (the bank) full of >> agents (accounts). Then I switched to a map full of atoms thinking that I >> don't really need asynchronous operations. I settled to the single ref >> approach because it seemed like an overkill to have all these refs inside. >> Your comment however does make sense...Since there is a single identity, >> perhaps STM is an overkill... >> >> 2. can you ellaborate why you think this is debatable? All the >> ref-managing fns return the in-transaction value of the ref (i.e. 'alter'). >> My problem was with 'doseq' which returns nil so I followed the general >> approach of returning the in-transaction value of the ref after it commits. >> >> 3. As I understand it these 2 transactions will be composed/merged into a >> single transaction. Again, originally I had a bare 'alter' (no dosync) on >> the private fn transfer1 simply because it is hidden and not supposed to be >> used...think of it as a helper fn for 'transfer'. but then I read somewhere >> that transaction can be nested without a problem so I thought it is safer >> to include 'dosync' in tranfer1 as well... >> >> I'm not getting you wrong, don't worry...this is the reason I started >> this thread - need some answers /feedback :) >> >> Jim >> >> >> On 21/11/13 10:42, Stefan Kamphausen wrote: >> >>> Hi, >>> >>> I may be missing something here, since this thread leaves me a bit >>> confused. >>> >>> 1. Why are you using a Ref for the bank in the first place? It is a >>> single identity and thus should be an atom, because you do not need to >>> coordinate changes of at least two identities. >>> >>> If I am not mistaken, the generic bank transfer example is to have a Ref >>> for each of the accounts and to make sure, that there is never a state of >>> the world in which the money is missing or is available twice. >>> >>> 2. "Even our side-effecting fns return something (per alter) which is >>> good." -> That seems debatable to me. >>> >>> 3. Why do you nest transactions on the same Ref in transfer1 and >>> transfer? >>> >>> Don't get me wrong, what you're doing may be fine. In that case, I just >>> don't get it. Which, in turn, may be a relevant feedback to you, since >>> this is to be educational :-) >>> >>> >>> Kind regards, >>> Stefan >>> >>> >>> -- >>> -- >>> 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/groups/opt_out. >>> >> >> > -- > -- > 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/groups/opt_out. > -- -- 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/groups/opt_out. -- -- 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/groups/opt_out. -- -- 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/groups/opt_out.