Is there an easier way to code this? Destructuring?

14 views
Skip to first unread message

Daniel Glauser

unread,
Jul 28, 2010, 8:02:18 PM7/28/10
to Clojure
Hello folks,

I'm working on some sample code and I have a feeling that there is an
easier/more succinct way to code this. Any help or RTFM with a link
is appreciated.

Given:

(def cookbook {:Coffee {:coffee 3, :sugar 1, :cream 1},
:Decaf-Coffee {:decaf 3, :sugar 1, :cream 1},
:Caffe-Late {:espresso 2, :steamed-milk 1},
:Caffe-Americano {:espresso 3},
:Caffe-Moca {:espresso 1, :coco 1, :steamed-milk
1, :cream 1},
:Cappuccino {:espresso 2, :steamed-milk 1, :foamed-milk
1} })

(def cost {:coffee 0.75,
:decaf 0.75,
:sugar 0.25,
:cream 0.25,
:steamed-milk 0.35,
:foamed-milk 0.35,
:espresso 1.00,
:cocoa 0.90,
:whipped-cream 1.00 })

(def menu {:Coffee 1,
:Decaf-Coffee 2,
:Caffe-Late 3,
:Caffe-Americano 4,
:Caffe-Moca 5,
:Cappuccino 6 })

I'm trying to write a function to print out the menu listing the cost
of each drink. It works (sort of) but I keep thinking there is an
easier way.

(defn print-menu [menu]
(do
(println "Menu:")
(doseq [[drink number] menu]
(println (str number ", " (drink-name drink) ", "
(reduce +
(map (fn [map-entry] (* (cost (key map-entry) (val map-
entry)))) (cookbook drink))))))))

Specifically this part:
(map (fn [map-entry] (* (cost (key map-entry) (val map-entry))))
(cookbook drink))

Is there a way I can get at the map key and value using destructuring
without knowing what the key is ahead of time?

Thanks,
Daniel

Nikita Beloglazov

unread,
Jul 29, 2010, 8:59:43 AM7/29/10
to clo...@googlegroups.com
Hi, Daniel
Here's my variant
https://gist.github.com/49c6ac95b7456a150df8

Note, that in cookbook :Caffe-Moca should contain :cocoa, not :coco
And I your variant calculating drink cost works incorrectly.
(* (cost (key map-entry) (val map-entry)))
should be replaced by
(* (cost (key map-entry)) (val map-entry))

Regards,
Nikita Beloglazov

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Laurent PETIT

unread,
Jul 29, 2010, 8:59:44 AM7/29/10
to clo...@googlegroups.com
Hi, not really "simplifying" (in the sense of removing code), but (tentatively ?) de-obfuscating:

(defn print-menu [menu]
  (do
    (println "Menu:")
    (doseq [[drink number] menu]
      (println 
        (str number ", " (drink-name drink) ", "
          (reduce 
            (fn [acc-cost [ingredient quantity]] 
              (+ acc-cost (* (cost ingredient) quantity)))
            (cookbook drink)))))))

Note that I got rid of the intermediate map

But I think that I would certainly divide it in more manageable pieces:

(defn- drink-name [drink] (name drink))
(defn- drink-cost [drink]
  (reduce 
    (fn [acc-cost [ingredient quantity]] 
      (+ acc-cost (* (cost ingredient) quantity)))
    0
    (cookbook drink)))

(defn print-menu [menu]
  (println "Menu:")
  (doseq [[drink number] menu]
    (println (str number ", " (drink-name drink) ", " (drink-cost drink)))))

HTH,

-- 
Laurent

2010/7/29 Daniel Glauser <dangl...@gmail.com>

joegg

unread,
Jul 29, 2010, 9:49:01 AM7/29/10
to Clojure
I agree with Laurent's idea that you should pull this out as a
separate function, but I think the most direct answer to your question
is that you can bind the map entries in a destructuring as if they
were two-element vectors.

(map (fn [[ingr quant]] (* (cost ingr) quant)) (cookbook drink))

Joe

Daniel Glauser

unread,
Jul 30, 2010, 4:30:49 PM7/30/10
to Clojure
Hi Joe, Laurent and Nikita,

Thanks for your help, the destructuring form of [[k v]] is much
cleaner, that's exactly what I was looking for.
Nikita, thanks for catching the typo and the misplaced paren, the code
is working smoothly now.

I have problem coded in Java, I plan to complete the Clojure version
and enhance both versions to support concurrent baristas and
customers. I'll post the code up in GitHub when I'm done if anyone
else would like the use the examples.

Cheers,
Daniel
Reply all
Reply to author
Forward
0 new messages