Re: another n00b defrecord combination question
Great stuff Ben. Thanks. ray On Saturday, December 15, 2012 10:54:42 PM UTC+1, Benjamin R. Haskell wrote: On Sat, 15 Dec 2012, mond wrote: Thanks for picking up the cudgels Ben! Ha. It's nice to have reached a point where I feel at-all confident with any of this... happy to help. To be honest I am struggling to repeat your advice in the REPL. In any case, I decided to change the data structures in line with your advice and put the IDs into maps rather than the records. (defrecord Item [name product quantity purchased]) (defrecord Product [name description prices]) (defrecord Price [price tax currency]) (def items [ {:id 1 :item (-Item Brogues P-123 1 true)} {:id 2 :item (-Item Underpants P-345 2 false)} {:id 3 :item (-Item Shirt P-678 1 true)} ]) (def carts [ (-Cart Birthday (first items)) (-Cart Xmas (rest items)) ]) (def products [ {:id P-1231 :product (-Product Table Coffee Table (-Price 375 21 EURO))} {:id P-3451 :product (-Product Chairs Set of Four(4) chairs (-Price 200 21 EURO))} {:id P-123 :product (-Product Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO))} {:id P-345 :product (-Product Underpants CK Y Fronts (-Price 23.50 21 EURO))} {:id P-678 :product (-Product Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO))} {:id P-6781 :product (-Product TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO))} ]) Do you think the zipmap is still the way to go (to resolve the 'foreign key' or could there be an easier way? I guess the fact that only items have to zipmapped is one advantage. It seems like items and products should still have an :id property, so I don't think you need to detach the ID from its entity. The zipmap'ed version is useful as an index, not really as its own structure. So, it ends up as just a single map (not an array of maps) with ID's as keys, and the corresponding entity as the value: (defrecord Item [id name product quantity purchased]) (defrecord Product [id name description prices]) (defrecord Price [price tax currency]) (def items [ (-Item 1 Brogues P-123 1 true) (-Item 2 Underpants P-345 2 false) (-Item 3 Shirt P-678 1 true) ]) (def products [ (-Product P-1231 Table Coffee Table (-Price 375 21 EURO)) (-Product P-3451 Chairs Set of Four(4) chairs (-Price 200 21 EURO)) (-Product P-123 Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO)) (-Product P-345 Underpants CK Y Fronts (-Price 23.50 21 EURO)) (-Product P-678 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO)) (-Product P-6781 TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO)) ]) ; two useful indexes(/indices?): (def prod-item An index from Product ID to an Item (zipmap (map :product items) items)) (def id-product An index from Product ID to a Product (zipmap (map :id products) products)) ; Then you can use that to get the products joined with their items: (defn product-with-item Find the Item info and merge it into the product, without overwriting :id [product] (merge-with (fn [a b] a) product (prod-item (:id product ; example usage: (product-with-item (id-product P-345)) ;= #user.Product{:id 2, ; :name Underpants, ; :description CK Y Fronts, ; :prices #user.Price{:price 23.5, :tax 21, :currency EURO}, ; :purchased false, ; :quantity 2, ; :product P-345} (def joined-products (map product-with-item products)) ;= A list of all the products joined with their items -- Best, Ben -- 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
Re: another n00b defrecord combination question
One small thing Ben... when I try to use the final formulation I receive an error: (def joined-products (map product-with-item products)) user= (joined-products) ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn user/eval241 (NO_SOURCE_FILE:9) Any ideas? Thanks in advance ray On Saturday, December 15, 2012 10:54:42 PM UTC+1, Benjamin R. Haskell wrote: On Sat, 15 Dec 2012, mond wrote: Thanks for picking up the cudgels Ben! Ha. It's nice to have reached a point where I feel at-all confident with any of this... happy to help. To be honest I am struggling to repeat your advice in the REPL. In any case, I decided to change the data structures in line with your advice and put the IDs into maps rather than the records. (defrecord Item [name product quantity purchased]) (defrecord Product [name description prices]) (defrecord Price [price tax currency]) (def items [ {:id 1 :item (-Item Brogues P-123 1 true)} {:id 2 :item (-Item Underpants P-345 2 false)} {:id 3 :item (-Item Shirt P-678 1 true)} ]) (def carts [ (-Cart Birthday (first items)) (-Cart Xmas (rest items)) ]) (def products [ {:id P-1231 :product (-Product Table Coffee Table (-Price 375 21 EURO))} {:id P-3451 :product (-Product Chairs Set of Four(4) chairs (-Price 200 21 EURO))} {:id P-123 :product (-Product Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO))} {:id P-345 :product (-Product Underpants CK Y Fronts (-Price 23.50 21 EURO))} {:id P-678 :product (-Product Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO))} {:id P-6781 :product (-Product TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO))} ]) Do you think the zipmap is still the way to go (to resolve the 'foreign key' or could there be an easier way? I guess the fact that only items have to zipmapped is one advantage. It seems like items and products should still have an :id property, so I don't think you need to detach the ID from its entity. The zipmap'ed version is useful as an index, not really as its own structure. So, it ends up as just a single map (not an array of maps) with ID's as keys, and the corresponding entity as the value: (defrecord Item [id name product quantity purchased]) (defrecord Product [id name description prices]) (defrecord Price [price tax currency]) (def items [ (-Item 1 Brogues P-123 1 true) (-Item 2 Underpants P-345 2 false) (-Item 3 Shirt P-678 1 true) ]) (def products [ (-Product P-1231 Table Coffee Table (-Price 375 21 EURO)) (-Product P-3451 Chairs Set of Four(4) chairs (-Price 200 21 EURO)) (-Product P-123 Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO)) (-Product P-345 Underpants CK Y Fronts (-Price 23.50 21 EURO)) (-Product P-678 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO)) (-Product P-6781 TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO)) ]) ; two useful indexes(/indices?): (def prod-item An index from Product ID to an Item (zipmap (map :product items) items)) (def id-product An index from Product ID to a Product (zipmap (map :id products) products)) ; Then you can use that to get the products joined with their items: (defn product-with-item Find the Item info and merge it into the product, without overwriting :id [product] (merge-with (fn [a b] a) product (prod-item (:id product ; example usage: (product-with-item (id-product P-345)) ;= #user.Product{:id 2, ; :name Underpants, ; :description CK Y Fronts, ; :prices #user.Price{:price 23.5, :tax 21, :currency EURO}, ; :purchased false, ; :quantity 2, ; :product P-345} (def joined-products (map product-with-item products)) ;= A list of all the products joined with their items -- Best, Ben -- 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
Re: another n00b defrecord combination question
On Sun, 16 Dec 2012, mond wrote: One small thing Ben... when I try to use the final formulation I receive an error: (def joined-products (map product-with-item products)) user= (joined-products) ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn user/eval241 (NO_SOURCE_FILE:9) Any ideas? To evaluate a list, Clojure tries to call the first element as a function, with the remaining elements as its arguments. So, in this case: (joined-products) Clojure tries to cast the first element of the list (joined-products) to be used as a Clojure function (clojure.lang.IFn), but it's a lazy sequence (clojure.lang.LazySeq). You just don't need the list: user= joined-products (#user.Product{...} #user.Product{...} #user.Product{...} ...) -- Best, Ben -- 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
Re: another n00b defrecord combination question
Hilarious - I am so conditioned already to have everything in a list :) Thanks for your patient explanation. Merry xmas. ray Ray On Sunday 16 December 2012 at 22:20, Benjamin R. Haskell wrote: On Sun, 16 Dec 2012, mond wrote: One small thing Ben... when I try to use the final formulation I receive an error: (def joined-products (map product-with-item products)) user= (joined-products) ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn user/eval241 (NO_SOURCE_FILE:9) Any ideas? To evaluate a list, Clojure tries to call the first element as a function, with the remaining elements as its arguments. So, in this case: (joined-products) Clojure tries to cast the first element of the list (joined-products) to be used as a Clojure function (clojure.lang.IFn), but it's a lazy sequence (clojure.lang.LazySeq). You just don't need the list: user= joined-products (#user.Product{...} #user.Product{...} #user.Product{...} ...) -- Best, Ben -- 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 (mailto: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 (mailto: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 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
Re: another n00b defrecord combination question
Hi, Ray. When you are doing things that have a relational algebra feel to them (joins, etc.), you might want to consider the fns in the clojure.set namespace. E.g.: ;; convert vectors of records to sets, then: (clojure.set/join (clojure.set/rename items {:id :iid :name :iname}) ; to prevent overwriting keys in the result products {:product :id}) ; 'where items.product = products.id' = #{ {:prices #user.Price{:price 45.99, :tax-rate 21, :currency EURO}, :description Slim Fit White Vest Shirt, :name Shirt, :id P-678, :iid 3, :product P-678, :quantity 1, :purchased true, :iname Shirt} ...} It might look even nicer if you just used regular maps with namespaced keys instead of records: (clojure.set/join items products {:item/product :product/id}) Hope that helps, Leif On Saturday, December 15, 2012 11:25:59 AM UTC-5, mond wrote: I have defined these types of records for modelling a simple shopping cart: ; An item in the cart (defrecord Item [id name product quantity purchased]) ; The product that relates to the item in the cart (defrecord Product [id name description prices]) ; A price definition (defrecord Price [price tax-rate currency]) ; Sample items (def items [ (-Item 1 Brogues P-123 1 true) (-Item 2 Underpants P-345 1 false) (-Item 3 Shirt P-678 1 true) ]) ; Sample products (def products [ (-Product P-123 Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO)) (-Product P-345 Underpants CK Y Fronts (-Price 23.50 21 EURO)) (-Product P-678 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO)) (-Product P-1231 Table Coffee Table (-Price 375 21 EURO)) (-Product P-3451 Chairs Set of Four(4) chairs (-Price 200 21 EURO)) (-Product P-6781 TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO)) ]) My requirement is to combine data from the two collections such that I can show the detailed product information for any item, for example: (-Item 3 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO) 1 true) When I tried to use merge-with union I had an error which surprised me since I thought records are also maps: user= (merge-with union items products) ClassCastException user.Product cannot be cast to java.util.Map$Entry clojure.core/key (core.clj:1465) Although I will fight on, any tips from any of you that have done this before would be greatly helped. Thanks ray -- 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
Re: another n00b defrecord combination question
I think I am close to answering this myself (which is always nice!) I have done the necessary joins with map and I can return a product description user= (map (fn [item product] (= (:product item (:id product))) (:description product)) items products) (Men's Leather Slip on Brogues CK Y Fronts Slim Fit White Vest Shirt) Or a purchased status for the matching item user= (map (fn [item product] (= (:product item (:id product))) (:purchased item)) items products) (true false true) But I have my knickers in a twist when I want to get more than one value out or a combination of values. user= (map (fn [item product] (= (:product item (:id product))) (:id item :description product)) items products) (user= IllegalArgumentException Wrong number of args passed to keyword: :id clojure.lang.Keyword.throwArity (Keyword.java:85) So does anyone have the last bit of syntax to help me take back a list of values from the inputs? Thanks ray On Saturday, December 15, 2012 5:25:59 PM UTC+1, mond wrote: I have defined these types of records for modelling a simple shopping cart: ; An item in the cart (defrecord Item [id name product quantity purchased]) ; The product that relates to the item in the cart (defrecord Product [id name description prices]) ; A price definition (defrecord Price [price tax-rate currency]) ; Sample items (def items [ (-Item 1 Brogues P-123 1 true) (-Item 2 Underpants P-345 1 false) (-Item 3 Shirt P-678 1 true) ]) ; Sample products (def products [ (-Product P-123 Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO)) (-Product P-345 Underpants CK Y Fronts (-Price 23.50 21 EURO)) (-Product P-678 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO)) (-Product P-1231 Table Coffee Table (-Price 375 21 EURO)) (-Product P-3451 Chairs Set of Four(4) chairs (-Price 200 21 EURO)) (-Product P-6781 TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO)) ]) My requirement is to combine data from the two collections such that I can show the detailed product information for any item, for example: (-Item 3 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO) 1 true) When I tried to use merge-with union I had an error which surprised me since I thought records are also maps: user= (merge-with union items products) ClassCastException user.Product cannot be cast to java.util.Map$Entry clojure.core/key (core.clj:1465) Although I will fight on, any tips from any of you that have done this before would be greatly helped. Thanks ray -- 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
Re: another n00b defrecord combination question
OK - I have it now: (map (fn [item product] (= (:product item (:id product))) [(:id item) (:description product)]) items products) This feels OK to me but if anyone has a nicer / more idiomatic solution, I will be happy to take feedback. ray On Saturday, December 15, 2012 7:08:21 PM UTC+1, mond wrote: I think I am close to answering this myself (which is always nice!) I have done the necessary joins with map and I can return a product description user= (map (fn [item product] (= (:product item (:id product))) (:description product)) items products) (Men's Leather Slip on Brogues CK Y Fronts Slim Fit White Vest Shirt) Or a purchased status for the matching item user= (map (fn [item product] (= (:product item (:id product))) (:purchased item)) items products) (true false true) But I have my knickers in a twist when I want to get more than one value out or a combination of values. user= (map (fn [item product] (= (:product item (:id product))) (:id item :description product)) items products) (user= IllegalArgumentException Wrong number of args passed to keyword: :id clojure.lang.Keyword.throwArity (Keyword.java:85) So does anyone have the last bit of syntax to help me take back a list of values from the inputs? Thanks ray On Saturday, December 15, 2012 5:25:59 PM UTC+1, mond wrote: I have defined these types of records for modelling a simple shopping cart: ; An item in the cart (defrecord Item [id name product quantity purchased]) ; The product that relates to the item in the cart (defrecord Product [id name description prices]) ; A price definition (defrecord Price [price tax-rate currency]) ; Sample items (def items [ (-Item 1 Brogues P-123 1 true) (-Item 2 Underpants P-345 1 false) (-Item 3 Shirt P-678 1 true) ]) ; Sample products (def products [ (-Product P-123 Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO)) (-Product P-345 Underpants CK Y Fronts (-Price 23.50 21 EURO)) (-Product P-678 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO)) (-Product P-1231 Table Coffee Table (-Price 375 21 EURO)) (-Product P-3451 Chairs Set of Four(4) chairs (-Price 200 21 EURO)) (-Product P-6781 TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO)) ]) My requirement is to combine data from the two collections such that I can show the detailed product information for any item, for example: (-Item 3 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO) 1 true) When I tried to use merge-with union I had an error which surprised me since I thought records are also maps: user= (merge-with union items products) ClassCastException user.Product cannot be cast to java.util.Map$Entry clojure.core/key (core.clj:1465) Although I will fight on, any tips from any of you that have done this before would be greatly helped. Thanks ray -- 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
Re: another n00b defrecord combination question
(responses inline) On Sat, 15 Dec 2012, mond wrote: I have defined these types of records for modelling a simple shopping cart: ; An item in the cart (defrecord Item [id name product quantity purchased]) ; The product that relates to the item in the cart (defrecord Product [id name description prices]) ; A price definition (defrecord Price [price tax-rate currency]) ; Sample items (def items [ (-Item 1 Brogues P-123 1 true) (-Item 2 Underpants P-345 1 false) (-Item 3 Shirt P-678 1 true) ]) ; Sample products (def products [ (-Product P-123 Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO)) (-Product P-345 Underpants CK Y Fronts (-Price 23.50 21 EURO)) (-Product P-678 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO)) (-Product P-1231 Table Coffee Table (-Price 375 21 EURO)) (-Product P-3451 Chairs Set of Four(4) chairs (-Price 200 21 EURO)) (-Product P-6781 TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO)) ]) My requirement is to combine data from the two collections such that I can show the detailed product information for any item, for example: (-Item 3 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO) 1 true) When I tried to use merge-with union I had an error which surprised me since I thought records are also maps: user= (merge-with union items products) ClassCastException user.Product cannot be cast to java.util.Map$Entry clojure.core/key (core.clj:1465) It looks like your second response worked around it, but for anyone following along: merge-with takes two or more maps, and uses the function you pass to merge the values of common keys. So, the error is caused because merge-with expects items and products to be maps (not vectors of map-like things). On Sat, 15 Dec 2012, mond wrote: I think I am close to answering this myself (which is always nice!) I have done the necessary joins with map and I can return a product description user= (map (fn [item product] (= (:product item (:id product))) (:description product)) items products) (Men's Leather Slip on Brogues CK Y Fronts Slim Fit White Vest Shirt) The (= (:product item (:id product))) here is being ignored. It works because your example arrays happen to have the items and products lined up properly (first three products match the items in order): (map (fn [item product] (= (:product item (:id product))) ; the result of this comparison is thrown away (:description product) ; this is the value that is returned ) items products) If you want to match things up, you might be better off creating maps for each category of thing: ; (with items and products as you'd defined them before) (def product-item (zipmap (map :product items) items)) ;= {P-123 #user.Item{...}, P-345 #user.Item{...}, ...} (def id-product (zipmap (map :id products) products)) ;= {P-123 #user.Product{...}, P-345 #user.Product{...}, ...} (def combined (merge-with union product-item id-product)) ;= {P-123 #user.Product{... with :quantity and :purchased }, ;P-1231 #user.Product{... with no Item keys ...}, ...etc. Or a purchased status for the matching item user= (map (fn [item product] (= (:product item (:id product))) (:purchased item)) items products) (true false true) But I have my knickers in a twist when I want to get more than one value out or a combination of values. user= (map (fn [item product] (= (:product item (:id product))) (:id item :description product)) items products) (user= IllegalArgumentException Wrong number of args passed to keyword: :id clojure.lang.Keyword.throwArity (Keyword.java:85) So does anyone have the last bit of syntax to help me take back a list of values from the inputs? Other than the matching issue (the = form isn't being used -- see above), the problem with what you've written is that you want a map, rather than a list: (map (fn [item product] {:id item :description product}) items products) Or if you really want a list, you need to quote it: (map (fn [item product] '(:id item :description product)) items products) -- Best, Ben -- 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
Re: another n00b defrecord combination question
On Sat, 15 Dec 2012, Benjamin R. Haskell wrote: Or if you really want a list, you need to quote it: (map (fn [item product] '(:id item :description product)) items products) Oops, wrong. Rather, you would want clojure.core/list: (map (fn [item product] (list :id item :description product)) items products) -- Best, Ben -- 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
Re: another n00b defrecord combination question
Thanks for picking up the cudgels Ben! To be honest I am struggling to repeat your advice in the REPL. In any case, I decided to change the data structures in line with your advice and put the IDs into maps rather than the records. (defrecord Item [name product quantity purchased]) (defrecord Product [name description prices]) (defrecord Price [price tax currency]) (def items [ {:id 1 :item (-Item Brogues P-123 1 true)} {:id 2 :item (-Item Underpants P-345 2 false)} {:id 3 :item (-Item Shirt P-678 1 true)} ]) (def carts [ (-Cart Birthday (first items)) (-Cart Xmas (rest items)) ]) (def products [ {:id P-1231 :product (-Product Table Coffee Table (-Price 375 21 EURO))} {:id P-3451 :product (-Product Chairs Set of Four(4) chairs (-Price 200 21 EURO))} {:id P-123 :product (-Product Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO))} {:id P-345 :product (-Product Underpants CK Y Fronts (-Price 23.50 21 EURO))} {:id P-678 :product (-Product Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO))} {:id P-6781 :product (-Product TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO))} ]) Do you think the zipmap is still the way to go (to resolve the 'foreign key' or could there be an easier way? I guess the fact that only items have to zipmapped is one advantage. Thanks for your support ray On Saturday, December 15, 2012 7:53:32 PM UTC+1, Benjamin R. Haskell wrote: On Sat, 15 Dec 2012, Benjamin R. Haskell wrote: Or if you really want a list, you need to quote it: (map (fn [item product] '(:id item :description product)) items products) Oops, wrong. Rather, you would want clojure.core/list: (map (fn [item product] (list :id item :description product)) items products) -- Best, Ben -- 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
Re: another n00b defrecord combination question
On Sat, 15 Dec 2012, mond wrote: Thanks for picking up the cudgels Ben! Ha. It's nice to have reached a point where I feel at-all confident with any of this... happy to help. To be honest I am struggling to repeat your advice in the REPL. In any case, I decided to change the data structures in line with your advice and put the IDs into maps rather than the records. (defrecord Item [name product quantity purchased]) (defrecord Product [name description prices]) (defrecord Price [price tax currency]) (def items [ {:id 1 :item (-Item Brogues P-123 1 true)} {:id 2 :item (-Item Underpants P-345 2 false)} {:id 3 :item (-Item Shirt P-678 1 true)} ]) (def carts [ (-Cart Birthday (first items)) (-Cart Xmas (rest items)) ]) (def products [ {:id P-1231 :product (-Product Table Coffee Table (-Price 375 21 EURO))} {:id P-3451 :product (-Product Chairs Set of Four(4) chairs (-Price 200 21 EURO))} {:id P-123 :product (-Product Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO))} {:id P-345 :product (-Product Underpants CK Y Fronts (-Price 23.50 21 EURO))} {:id P-678 :product (-Product Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO))} {:id P-6781 :product (-Product TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO))} ]) Do you think the zipmap is still the way to go (to resolve the 'foreign key' or could there be an easier way? I guess the fact that only items have to zipmapped is one advantage. It seems like items and products should still have an :id property, so I don't think you need to detach the ID from its entity. The zipmap'ed version is useful as an index, not really as its own structure. So, it ends up as just a single map (not an array of maps) with ID's as keys, and the corresponding entity as the value: (defrecord Item [id name product quantity purchased]) (defrecord Product [id name description prices]) (defrecord Price [price tax currency]) (def items [ (-Item 1 Brogues P-123 1 true) (-Item 2 Underpants P-345 2 false) (-Item 3 Shirt P-678 1 true) ]) (def products [ (-Product P-1231 Table Coffee Table (-Price 375 21 EURO)) (-Product P-3451 Chairs Set of Four(4) chairs (-Price 200 21 EURO)) (-Product P-123 Brogues Men's Leather Slip on Brogues (-Price 93.00 21 EURO)) (-Product P-345 Underpants CK Y Fronts (-Price 23.50 21 EURO)) (-Product P-678 Shirt Slim Fit White Vest Shirt (-Price 45.99 21 EURO)) (-Product P-6781 TableCloth Classic red and white checks 2m x 2m (-Price 17.99 21 EURO)) ]) ; two useful indexes(/indices?): (def prod-item An index from Product ID to an Item (zipmap (map :product items) items)) (def id-product An index from Product ID to a Product (zipmap (map :id products) products)) ; Then you can use that to get the products joined with their items: (defn product-with-item Find the Item info and merge it into the product, without overwriting :id [product] (merge-with (fn [a b] a) product (prod-item (:id product ; example usage: (product-with-item (id-product P-345)) ;= #user.Product{:id 2, ; :name Underpants, ; :description CK Y Fronts, ; :prices #user.Price{:price 23.5, :tax 21, :currency EURO}, ; :purchased false, ; :quantity 2, ; :product P-345} (def joined-products (map product-with-item products)) ;= A list of all the products joined with their items -- Best, Ben -- 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