Wow, thank you very much. That's definitely a lot simpler. I'm going to try reimplementing it via your suggestions and see how it goes.
I like your idea about not maintaining cart state on the server, because it would make my functions easier to test and debug (no need to setup & teardown a fake session) but I'm not sure it would work well in practice. If a user is browsing Amazon, for example, they might add something to their cart, then visit 10 random pages before they go to checkout. I would need to embed the cart in each of these pages and resubmit the cart to the server for each request. The purpose of sessions are to avoid exactly this hairy situation. I wrapped cart in a Ref in case multiple browser windows are open and there is a concurrent "add to cart" click. On Tue, Oct 27, 2009 at 12:41 PM, Timothy Pratley <timothyprat...@gmail.com> wrote: > > Hi Robert > > On Oct 27, 9:48 pm, Robert Campbell <rrc...@gmail.com> wrote: >> Hey guys, I'm looking for _any_ feedback/thoughts on this Clojure code >> I wrote. I just feel like the entire thing is way too complex, but I'm >> not sure about how to simplify it. I wanted to try something "real >> world" so I made a simple shopping cart ref to put in a session: > > Great, an open invitation! > > structs are really no different from maps except as a performance > optimisation (and not a huge one). So dropping the structs would > remove some boilerplate if simplicity is your goal. Also why not make > the cart a map of products to qty and forget about subtotal... > subtotal and total are easily calculated by separate functions for > view or checkout... something like (untested at all): > > (defn add-to-cart [product qty] > (if (pos? qty) > (dosync (alter cart update-in [product] #(+ qty (if % % 0))))) > > (defn update-cart [product qty] > (dosync (alter cart assoc product qty))) > > (defn remove [product] > (dosync (alter cart dissoc product))) > > (defn subtotal [product] > (* (@cart product) (price product))) > > (defn total [] > (reduce + (map subtotal @cart))) > > But in a real-world example I'm not sure a ref would be the best way > to deal with the state... wouldn't you have the cart sent up in the > request and a new cart returned? ie: you wouldn't need to maintain a > ref on the server, just provide the hooks for building a cart and > checking out. So the functions might be better if they take a cart as > input and return a cart. Doing that pretty much makes them empty > functions: > (defn remove [cart product] > (dissoc cart product)) > So do you even need a remove function? Maybe not. > > Just some thoughts - I'm no web-shop programmer so disclaimer > attached. > > > Regards, > Tim. > > > > Regards, > Tim. > > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---