I second Tim's comment regarding holding onto calculated values.
That's at best a performance optimization, and likely an unnecessary
one.

Also, by using the product itself as a key simplifies the case where
you try to "add" the same product as multiple line-items (though this
may be what you want if there are other considerations at play).

But as to the code you have, I'd suggest using some higher-level
functions. For example, change this:


(defn add-line-item [cart line-item]
  (assoc cart
    :line-items (conj (cart :line-items) line-item)
    :total (+ (cart :total) (line-item :subtotal))))

to this:

(defn add-line-item [c li]
  (-> c (update-in [:line-items] conj li)
        (update-in [:total] + (:subtotal li))))

Likewise, you could change this:

(defn update-line-item [line-items product qty]
  (cond
    (empty? line-items) ()
    (= ((first line-items) :product) product)
        (cons
            (assoc (first line-items)
                :qty qty
                :subtotal (* qty (((first line-
items) :product) :price)))
            (rest line-items))
    :else
        (cons (first line-items)
            (update-line-item (rest line-items) product qty))))

to this:

(defn update-line-item [cart product qty]
  (-> cart (assoc :line-items (filter #(= product (:product %)) cart))
           (add-line-item (create-line-item product qty))))

Etc...



On Oct 27, 4:41 am, 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
-~----------~----~----~----~------~----~------~--~---

Reply via email to