Re: another n00b defrecord combination question

2012-12-16 Thread mond
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

2012-12-16 Thread mond
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

2012-12-16 Thread Benjamin R. Haskell

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

2012-12-16 Thread Ray
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

2012-12-16 Thread Leif
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

2012-12-15 Thread mond
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

2012-12-15 Thread mond
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

2012-12-15 Thread Benjamin R. Haskell

(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

2012-12-15 Thread Benjamin R. Haskell

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

2012-12-15 Thread mond
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

2012-12-15 Thread Benjamin R. Haskell

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