Re: vec to map with consolidated vals
Ah, I misunderstood your requirements, but I'm glad it led you in the right direction! On Fri, Aug 16, 2013 at 10:40 PM, David Chelimsky dchelim...@gmail.com wrote: Thanks for the suggestions Sean and Ben. I learned new functions from both of you! Sean, your suggestion yields the following: (to-consolidated-map [[:a 1] [:b 2] [:a 3]]) ; {:a (1 3) :b (2)} So it still needs to reduce the vals using +. That led me to this: (defn to-consolidated-map [parts] (apply merge-with + (map (fn [[k v]] {k v}) parts))) Which led me to this: (defn to-consolidated-map [parts] (apply merge-with + (map (partial apply hash-map) parts))) I like this one because it describes the solution the way I thought about it - I just didn't know about merge-with. It also has the benefit of using core fns rather than anonymous fns. WDYT? On Sat, Aug 17, 2013 at 7:23 AM, Sean Corfield seancorfi...@gmail.com wrote: How about this: (defn to-consolidated-map [parts] (apply merge-with concat (map (fn [[k v]] {k (list v)}) parts))) On Fri, Aug 16, 2013 at 9:57 PM, David Chelimsky dchelim...@gmail.com wrote: I've got a vector of 2-element vectors e.g. [[:a 1] [:b 2]] where the first val of any vec might appear in another vec e.g. [[:a 1] [:b 2] [:a 3]]. I need a fn that will consolidate this into a hash-map with the vals consolidated e.g. (to-consolidated-map [[:a 1] [:b 2] [:a 3]]) ; {:a 4 :b 2} I've got two candidate implementations and I'm curious which you like better and why, or if I'm missing a better way: (defn to-consolidated-map [parts] (reduce (fn [h [k v]] (if (contains? h k) (assoc h k (+ (k h) v)) (assoc h k v))) {} parts)) (defn to-consolidated-map [parts] (- parts (group-by first) (map (fn [[k v]] [k (- v (map last) (reduce +))] TIA, David -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- -- 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 --- You received this message because you are
Re: vec to map with consolidated vals
At first I came up with the same solution as your second one. But I couldn't help but feel that it wasn't descriptive enough. It felt too incidental-complexity-ish. To me, (into {} the-map) seems mostly right. But obviously it would just squash the values you need. So I figured it should just be modified a bit. Seeing as how it's really short for reduce conj, I figured conj was the place to swap out. Here's what I came up with: (def the-map [[:a 1] [:b 2] [:a 3]]) (defn add-maybe [ nums] (- nums (remove nil?) (reduce +))) (reduce (fn [m [k v]] (update-in m [k] add-maybe v)) {} the-map) ;; = {:b 2, :a 4} But I don't really like the add-maybe function. It seems like I'm probably missing an opportunity for a core-lib function that I'm forgetting about. I really just wanted to have access to the original value, so I could do (or orig-value 0) and then just use + instead of add-maybe. -Steven On Fri, Aug 16, 2013 at 11:57 PM, David Chelimsky dchelim...@gmail.comwrote: I've got a vector of 2-element vectors e.g. [[:a 1] [:b 2]] where the first val of any vec might appear in another vec e.g. [[:a 1] [:b 2] [:a 3]]. I need a fn that will consolidate this into a hash-map with the vals consolidated e.g. (to-consolidated-map [[:a 1] [:b 2] [:a 3]]) ; {:a 4 :b 2} I've got two candidate implementations and I'm curious which you like better and why, or if I'm missing a better way: (defn to-consolidated-map [parts] (reduce (fn [h [k v]] (if (contains? h k) (assoc h k (+ (k h) v)) (assoc h k v))) {} parts)) (defn to-consolidated-map [parts] (- parts (group-by first) (map (fn [[k v]] [k (- v (map last) (reduce +))] TIA, David -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: vec to map with consolidated vals
Wow. Sorry for the awful formatting. Re-pasting it from Google Groups (instead of email) to fix it: (def a [[:a 1] [:b 2] [:a 3]]) (defn add-maybe [ nums] (- nums (remove nil?) (reduce +))) (reduce (fn [m [k v]] (update-in m [k] add-maybe v)) {} a) ;; = {:b 2, :a 4} -Steven On Saturday, August 17, 2013 3:40:23 AM UTC-5, Steven Degutis wrote: At first I came up with the same solution as your second one. But I couldn't help but feel that it wasn't descriptive enough. It felt too incidental-complexity-ish. To me, (into {} the-map) seems mostly right. But obviously it would just squash the values you need. So I figured it should just be modified a bit. Seeing as how it's really short for reduce conj, I figured conj was the place to swap out. Here's what I came up with: (def the-map [[:a 1] [:b 2] [:a 3]]) (defn add-maybe [ nums] (- nums (remove nil?) (reduce +))) (reduce (fn [m [k v]] (update-in m [k] add-maybe v)) {} the-map) ;; = {:b 2, :a 4} But I don't really like the add-maybe function. It seems like I'm probably missing an opportunity for a core-lib function that I'm forgetting about. I really just wanted to have access to the original value, so I could do (or orig-value 0) and then just use + instead of add-maybe. -Steven On Fri, Aug 16, 2013 at 11:57 PM, David Chelimsky wrote: I've got a vector of 2-element vectors e.g. [[:a 1] [:b 2]] where the first val of any vec might appear in another vec e.g. [[:a 1] [:b 2] [:a 3]]. I need a fn that will consolidate this into a hash-map with the vals consolidated e.g. (to-consolidated-map [[:a 1] [:b 2] [:a 3]]) ; {:a 4 :b 2} I've got two candidate implementations and I'm curious which you like better and why, or if I'm missing a better way: (defn to-consolidated-map [parts] (reduce (fn [h [k v]] (if (contains? h k) (assoc h k (+ (k h) v)) (assoc h k v))) {} parts)) (defn to-consolidated-map [parts] (- parts (group-by first) (map (fn [[k v]] [k (- v (map last) (reduce +))] TIA, David -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: vec to map with consolidated vals
Oh. Wow, I should read the whole thread before posting. Seems like merge-with is what I was looking for. Although, lately both partial and apply make me a little uneasy in terms of efficiency. But that's easily enough solved with an anonymous function, which I don't think is any less readable (maybe even more readable): (apply merge-with + (map (fn [[k v]] {k v}) the-map)) -Steven On Sat, Aug 17, 2013 at 3:42 AM, Steven Degutis sbdegu...@gmail.com wrote: Wow. Sorry for the awful formatting. Re-pasting it from Google Groups (instead of email) to fix it: (def a [[:a 1] [:b 2] [:a 3]]) (defn add-maybe [ nums] (- nums (remove nil?) (reduce +))) (reduce (fn [m [k v]] (update-in m [k] add-maybe v)) {} a) ;; = {:b 2, :a 4} -Steven On Saturday, August 17, 2013 3:40:23 AM UTC-5, Steven Degutis wrote: At first I came up with the same solution as your second one. But I couldn't help but feel that it wasn't descriptive enough. It felt too incidental-complexity-ish. To me, (into {} the-map) seems mostly right. But obviously it would just squash the values you need. So I figured it should just be modified a bit. Seeing as how it's really short for reduce conj, I figured conj was the place to swap out. Here's what I came up with: (def the-map [[:a 1] [:b 2] [:a 3]]) (defn add-maybe [ nums] (- nums (remove nil?) (reduce +))) (reduce (fn [m [k v]] (update-in m [k] add-maybe v)) {} the-map) ;; = {:b 2, :a 4} But I don't really like the add-maybe function. It seems like I'm probably missing an opportunity for a core-lib function that I'm forgetting about. I really just wanted to have access to the original value, so I could do (or orig-value 0) and then just use + instead of add-maybe. -Steven On Fri, Aug 16, 2013 at 11:57 PM, David Chelimsky wrote: I've got a vector of 2-element vectors e.g. [[:a 1] [:b 2]] where the first val of any vec might appear in another vec e.g. [[:a 1] [:b 2] [:a 3]]. I need a fn that will consolidate this into a hash-map with the vals consolidated e.g. (to-consolidated-map [[:a 1] [:b 2] [:a 3]]) ; {:a 4 :b 2} I've got two candidate implementations and I'm curious which you like better and why, or if I'm missing a better way: (defn to-consolidated-map [parts] (reduce (fn [h [k v]] (if (contains? h k) (assoc h k (+ (k h) v)) (assoc h k v))) {} parts)) (defn to-consolidated-map [parts] (- parts (group-by first) (map (fn [[k v]] [k (- v (map last) (reduce +))] TIA, David -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: vec to map with consolidated vals
Of your proposed solutions, this one (defn to-consolidated-map [parts] (- parts (map (partial apply hash-map)) (apply merge-with +)) Is the one I thought of first and also find very readable. On Saturday, August 17, 2013, David Chelimsky wrote: Sorry - pressed send before refreshing and didn't see your response. Readability is a very subjective topic. I have an (possibly irrational) aversion to anonymous fns when core fns solve the same problem, so I'm very accustomed to reading things like (partial apply xxx). The perf issue would definitely push me over, however. On Sat, Aug 17, 2013 at 11:19 AM, David Chelimsky dchelim...@gmail.comwrote: Hey Steven, here's a variation of my first example that, I think, gets closer to what you're proposing (with maybe-add handled in-line): (defn to-consolidated-map [parts] (reduce (fn [h [k v]] (assoc h k (+ (get h k 0) v))) {} parts)) Using assoc instead of update-in allows it to handle nils with a default value to get. All core lib fns. WDYT? Also, this: (defn to-consolidated-map [parts] (apply merge-with + (map (partial apply hash-map) parts))) or this variant: (defn to-consolidated-map [parts] (- parts (map (partial apply hash-map)) (apply merge-with +)) each use only core lib fns, which you say you're looking for. I find this less accidental-complexity-ish than the implementations that use reduce with a custom (anonymous) fn, which each require handling nil in some fashion. WDYT? On Sat, Aug 17, 2013 at 10:42 AM, Steven Degutis sbdegu...@gmail.comwrote: Wow. Sorry for the awful formatting. Re-pasting it from Google Groups (instead of email) to fix it: (def a [[:a 1] [:b 2] [:a 3]]) (defn add-maybe [ nums] (- nums (remove nil?) (reduce +))) (reduce (fn [m [k -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: function creation, partial or #()
Sean, it sounds like you want (swap! some-a update-in [:k1 :k2] (fnil conj []) id) But that's based on some pretty limited context. On Friday, August 16, 2013, Sean Corfield wrote: On Fri, Aug 16, 2013 at 4:32 PM, Timothy Baldridge tbaldri...@gmail.comjavascript:; wrote: I'm just going to throw this out there, but I almost always consider using #() instead of (fn []) to be bad practice. I still use #() for anonymous single argument functions that are small, single forms, but I've started switching to (fn [..] ..) for anything even slightly more complex because, like you, I find having a named argument to be worth the extra typing, even if it is just a single letter, suggestive of the argument type. Today I found myself writing (fnil #(conj % id) []) a couple of times because (fnil (fn [v] (conj v id)) []) doesn't seem any clearer - but suggestions for nicer code are always welcome. It's part of (swap! some-atom update-in [:path :to :item] ...) if that helps :) Sean -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.comjavascript:; 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 javascript:; 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 unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com javascript:;. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Fwd: Hands-on Clojure: Collaborative Filtering
if any of you are in Cambridge (UK) next Thursday evening, you're be welcome to join us at the next Camclj Meetup. Details below. -- Forwarded message -- From: Ray Miller r...@1729.org.uk Date: 17 August 2013 15:47 Subject: Hands-on Clojure: Collaborative Filtering To: cam...@googlegroups.com Our next meetup will be a hands-on coding session along similar lines to the London Clojure Dojos [*]. We will have a go at implementing some collaborative filtering algorithms to make movie recommendations. Where? Upstairs at The Fountain, 12 Regent Street, Cambridge, CB2 1DB When? Thursday 22nd August 2013, from 1900-2200. Who? This event is open to all, from beginner to expert. Free beer! This meetup is sponsored by Metail, who are covering venue hire and the drinks. Metail is recruiting! If you want to work in an exciting startup environment where you can build out your Clojure webdev skils, check out the job listing http://metail.com/job/junior-web-software-engineer-clojure/. You don't need any prior Clojure experience to attend this event; we hope to have enough experienced developers on hand to get everyone started. Please sign up on Meetup if you plan to attend: http://meetu.ps/1Y34WR If you have a laptop, please bring it along. There are a couple of things you can do before the Meetup, you'll find some setup notes and suggested background reading (entirely optional!) here: http://github.com/cam-clj/Recommendations. It would be particularly useful if you could download the test data set and suggested dependencies before the Meetup, just in case the pub's wi-fi proves unreliable. On the day, look for us in the first floor room at the Fountain, which we have exclusive use of until 10pm. The pub doesn't do a wide range of food, but you will be able to order from a selection of flat breads at the bar until 9pm. I hope to see you next week! Ray. [*] http://otfrom.wordpress.com/2012/07/04/how-to-run-a-london-clojure-dojo-in-20ish-easy-steps/ -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Help to start creating this DSL in Clojure
Hi, I'm trying to create this Domain Specific Language: (query clojure (directory /usr/texts) (group-by :creation-date)) What it should do is to search for all files in a specific directory using a regexp and then group the result by some of files attributes. The idea is the (query) created a RegExp object. (directory) to specify which directory to scan. (group-by) is to group the files names by creation-date of the files. (query) will use Java RegExp library. (directory) will use java.io package. ** I know that I can use Clojure functions for RegExp and IO but I want to try to create it using Java libraries ** Any starting points are really appreciated. Thanks for help and time. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Help to start creating this DSL in Clojure
Hussein B.: Hi, I'm trying to create this Domain Specific Language: (query clojure (directory /usr/texts) (group-by :creation-date)) Any starting points are really appreciated. Take a look at http://clojure-doc.org/articles/tutorials/growing_a_dsl_with_clojure.html -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Generating a Java bean via Clojure?
Some Java frameworks will accept public final fields as Java bean fields. In that case, a Clojure record can be used directly (although I'm not sure if we're making an assumption about Clojure records that might change). This has actually worked for my limited needs in this space. The only other cases I've run into this are instances where I wanted to create a first-class Java (and javadoc'd) API for consumers, so I wrote a Java interface that followed JavaBean conventions, and simply reified it in Clojure. That all said, if I had to do this often (I haven't), I probably would have written some form of defbean macro that created a record and the corresponding getters for Java land. Unfortunately I'm not aware of such a thing, but it seems like it would be straightforward to implement. On Friday, August 16, 2013 12:29:40 PM UTC-5, Sean Corfield wrote: I was working with a Java library recently and needed to create a Java bean to pass into it. It can be done via `gen-class` but it seems kind of verbose having to explicitly write out all of the getters and setters, and it seems you could also do it via `deftype` but that's also rather painful (I started looking at that in the hope of automating it via a macro but it seemed difficult to have overloaded constructors and I needed both a no-arg constructor and one that took all the bean attributes). What do people do when they need a Java bean for interop when using Clojure with a Java library? This seems like it should be common enough that I would have expected it to be part of clojure.java.data but it isn't... Just a class name and a list of property names and (perhaps optional) types should be all the ceremony we need to write... and I don't want to reinvent the wheel if that is already out there somewhere? -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: [ANN] Leiningen 2.3.1 released
After upgrade to 2.3.1, I can't find repl-port file in target directory, so lein repl will use a random port, I have to use LEIN_REPL_PORT=33021 lein repl to assign the port. 2013/8/14 Sean Corfield seancorfi...@gmail.com Thank you! I've upgraded our team to 2.3.1, as well as our QA system. So far, no problems. Sean On Tue, Aug 13, 2013 at 10:37 AM, Phil Hagelberg p...@hagelb.org wrote: Hello folks. With some help from Nelson Morris I've pushed out the 2.3.1 release of Leiningen. This fixes the self-install issues as well as the issue around AOT classes not being included in jar files. It also adds a new flag (:monkeypatch-clojure-test false) you can use to disable Leiningen's monkeypatch of the `clojure.test` library. As usual, if you installed manually you can upgrade with `lein upgrade`. If you need to back out for some reason, you can downgrade with `lein upgrade 2.2.0`. -Phil -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Gensym collisions can be engineered.
Interesting discussion - I was pretty surprised to see this can happen I don't understand all the details about the solutions discussed in this thread, but it seems that the only way to ensure no local can be clobbered, gensym'ed or not, is to introduce into the RT a local resolution phase table which maps all user (as found in code) symbols in the current scope to a unique symbol - sort of a gensym for regular vars, to that in the following example, the local G__2244 defined by the user would get remapped internally. The table could be wiped out at the end of its scope...admittedly this is probably a challenge to provide for nested scopes. (defmacro clobber [ forms ] (let [ club (gensym) ] `(let [ ~club squirrel ] ~@forms ;;the following to help find a clobbered var in the scope ;; enclosing the macro call (println clobbering symbol: '~club) ))) give it a few REPL (gensym) tries, and: user= (let [ G__2244 mountain lion ] (clobber (println I am a G__2244))) I am a squirrel clobbering symbol: G__2244 On Saturday, November 7, 2009 11:59:08 PM UTC-5, John Harrop wrote: user= (def q 'G__723) #'user/q user= (def r (gensym)) #'user/r user= q G__723 user= r G__723 user= (= q r) true It's possible to anticipate the next gensym name that will be generated and then engineer a collision, and therefore possibly variable capture unintended by the author of a macro. It looks like manually generating a name does not remove it from the pool of allowable future gensym names. This shouldn't tend to cause accidental problems in practice, since gensym names tend not to collide with the kinds of identifiers programmers ordinarily use. Nonetheless it can be partially fixed comparatively easily by adding to the runtime a WeakHashMap into which a reference to any symbol, however created, is placed and modifying the gensym-generator to, at the point where it currently returns a value, first check if the WeakHashMap contains it already and if so, generate the next one, and the next, as needed until it gets a not-in-use name. This requires gensym creation and normal symbol creation to occur in a global lock but symbol creation rarely occurs at runtime and even more rarely in any kind of hot-spot at runtime. The use of WeakHashMap would prevent the runtime clogging up with ungarbagecollectable symbols, so the memory overhead of adding this would be smallish, one machine pointer per in-use symbol or so, equivalent to if every symbol had a few more characters in its name. This would stop gensym from producing a name already in use. It wouldn't prevent a gensym being generated somewhere and *then* the identical name being put together someplace else and passed to the symbol function, though; a small loophole. Collisions between gensyms in preexisting code and an enclosing lexical scope in new code would become impossible, but collisions between gensyms in preexisting code and an enclosed lexical scope (e.g. a macro-invocation body, such as a loop body) would remain theoretically possible. That last loophole can't really be plugged without giving Clojure true gensyms (uninterned anywhere), which would bring with it its own architectural problems. If that change were made, the above REPL interaction would be possible up to the (= q r) evaluation, but that would return false despite the names looking the same, so the symbols wouldn't really collide even though a collision of their printed representations could still be engineered. One bothersome consequence though would be that the textual output of macroexpand-1 could no longer always be substituted for a macro call in source code without altering the run-time semantics of that code, even when the macro's expansion-generation does not have side effects. (To reproduce that REPL interaction for yourself, evaluate (gensym) at the REPL and note the number. Add seven and then evaluate (def q 'G__#) with # replaced with the sum. Then evaluate (def r (gensym)) and, if you like, skip straight to (= q r). If that doesn't work, the number it goes up by must have changed between Clojure 1.0 and whatever version you're using; evaluate (gensym), then (def q 'xyzzy), then (gensym) again and note the increment and use that instead of seven. Oh, and don't have any background threads running in that JVM instance that might do something autonomously that causes a gensym to be generated.) -- -- 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,
Re: vec to map with consolidated vals
Yeah, I totally agree that using core fns instead of anonymous fns makes code way more readable and easier to mentally scan. The main reason I suggested the anonymous function was for performance, which is probably premature-optimization at this point. But I think I agree with you and Jay, that short one is probably best. Also I agree that your solution with (get) is better than the (update-in) version I had for the reasons you mentioned. -Steven On Sat, Aug 17, 2013 at 4:28 AM, David Chelimsky dchelim...@gmail.comwrote: Sorry - pressed send before refreshing and didn't see your response. Readability is a very subjective topic. I have an (possibly irrational) aversion to anonymous fns when core fns solve the same problem, so I'm very accustomed to reading things like (partial apply xxx). The perf issue would definitely push me over, however. On Sat, Aug 17, 2013 at 11:19 AM, David Chelimsky dchelim...@gmail.comwrote: Hey Steven, here's a variation of my first example that, I think, gets closer to what you're proposing (with maybe-add handled in-line): (defn to-consolidated-map [parts] (reduce (fn [h [k v]] (assoc h k (+ (get h k 0) v))) {} parts)) Using assoc instead of update-in allows it to handle nils with a default value to get. All core lib fns. WDYT? Also, this: (defn to-consolidated-map [parts] (apply merge-with + (map (partial apply hash-map) parts))) or this variant: (defn to-consolidated-map [parts] (- parts (map (partial apply hash-map)) (apply merge-with +)) each use only core lib fns, which you say you're looking for. I find this less accidental-complexity-ish than the implementations that use reduce with a custom (anonymous) fn, which each require handling nil in some fashion. WDYT? On Sat, Aug 17, 2013 at 10:42 AM, Steven Degutis sbdegu...@gmail.comwrote: Wow. Sorry for the awful formatting. Re-pasting it from Google Groups (instead of email) to fix it: (def a [[:a 1] [:b 2] [:a 3]]) (defn add-maybe [ nums] (- nums (remove nil?) (reduce +))) (reduce (fn [m [k v]] (update-in m [k] add-maybe v)) {} a) ;; = {:b 2, :a 4} -Steven On Saturday, August 17, 2013 3:40:23 AM UTC-5, Steven Degutis wrote: At first I came up with the same solution as your second one. But I couldn't help but feel that it wasn't descriptive enough. It felt too incidental-complexity-ish. To me, (into {} the-map) seems mostly right. But obviously it would just squash the values you need. So I figured it should just be modified a bit. Seeing as how it's really short for reduce conj, I figured conj was the place to swap out. Here's what I came up with: (def the-map [[:a 1] [:b 2] [:a 3]]) (defn add-maybe [ nums] (- nums (remove nil?) (reduce +))) (reduce (fn [m [k v]] (update-in m [k] add-maybe v)) {} the-map) ;; = {:b 2, :a 4} But I don't really like the add-maybe function. It seems like I'm probably missing an opportunity for a core-lib function that I'm forgetting about. I really just wanted to have access to the original value, so I could do (or orig-value 0) and then just use + instead of add-maybe. -Steven On Fri, Aug 16, 2013 at 11:57 PM, David Chelimsky wrote: I've got a vector of 2-element vectors e.g. [[:a 1] [:b 2]] where the first val of any vec might appear in another vec e.g. [[:a 1] [:b 2] [:a 3]]. I need a fn that will consolidate this into a hash-map with the vals consolidated e.g. (to-consolidated-map [[:a 1] [:b 2] [:a 3]]) ; {:a 4 :b 2} I've got two candidate implementations and I'm curious which you like better and why, or if I'm missing a better way: (defn to-consolidated-map [parts] (reduce (fn [h [k v]] (if (contains? h k) (assoc h k (+ (k h) v)) (assoc h k v))) {} parts)) (defn to-consolidated-map [parts] (- parts (group-by first) (map (fn [[k v]] [k (- v (map last) (reduce +))] TIA, David -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to
Re: logback.xml being picked up twice in project (how do I surpess the inheritted projects logback.xml)?
Thanks Laurent, I did as you suggest and things seem to be fine now. I ended up using :profiles = :dev = :source-paths in my project.clj to include the 'dev-resources' directory. Seems to be in use when I lein repl, but is not included when I build a jar. Probably there are other problems with that, but it seems to work well enough for me. On Thursday, August 15, 2013 11:39:19 PM UTC-7, Laurent PETIT wrote: 2013/8/16 Stephen Cagle sam...@gmail.com javascript:: Sorry if I am being dense, just want to make sure I understand what you are saying... So, I was including logback.xml in my git source control. I take it you would say that is a bad idea? I thought it made sense as I then have it as part of the project, but I suppose it could get in the way in situations like this. Do you gitignore your logback.xml and just have a custom logback.xml specified with logback.configurationFile for different aspects (development, testing, production)? A simple configuration idea (supposing you are using leiningen for projects base and derive, and that you own both projects so you can make changes to both). base plays the role of a library. A library should not impose logging settings on the final products that will use it. But you still need a logging file to test the library ! Just put a logback-test.xml file in your dev-resources directory. It's fine to have it in git, then, since it won't be part of the final jar now, it's all that matters. You do this for each library in your application. For the final product, the one you deliver, you can just have 2 configurations, one for test, one while developing: - place a file logback-test.xml in dev-resources. When it is present, it will be picked first, meaning it will be picked first in your local machine. - place the production file logback.xml in resources. This is a simple settings. It doesn't handle the case where you want different logback.xml files for test, staging and prod servers, for instance. YMMV. On Thursday, August 15, 2013 5:16:24 PM UTC-7, Jason Bennett wrote: The trick is, don't build the original jar with the logback config file. No dependent of that jar wants to be told how to do logging. You should keep your logback.xml in the /config directory, not in /resources. As far as -D, that's to pass environment parameters to the JVM. See http://logback.qos.ch/manual/configuration.html#configFileProperty for how to configure the logback.xml location that way. To recap: don't include logback.xml in any jars, anywhere (except for test versions, which logback supports). Have it living in production on the file system, and point to that file on startup. That way, you can have environment-specific logging configured in that environment. jason On Thu, Aug 15, 2013 at 5:06 PM, Stephen Cagle sam...@gmail.com wrote: I don't know what -D is, other than a one eyed laughing face. :D Is there some sort of standard for this? Do people simply write a script that checks out the code and remove files that they don't want in the generated jar? Is there something I can put in my project.clj that specifies what I don't want included in a generated jar? How do people generally go about it. Not that it is a big deal, mind you. It just seems a bit busy to have to write a special script that 1) checks out my code from github 2)removes the files I don't want in the jar 3) builds the jar 4) does whatever else I am forgetting. Seems like there might be something simpler that I don't know about. On Thursday, August 15, 2013 4:38:01 PM UTC-7, Jason Bennett wrote: You shouldn't include the logback.xml in the generated jar file. Only the ultimately generated artifact should have a logback.xml file, best loaded from the file system (possibly through -D). It doesn't matter what settings base has for logging, derive should set all logging parameters. jason On Thursday, August 15, 2013 3:51:04 PM UTC-7, Stephen Cagle wrote: I have project 'base' that has a logback.xml file and project 'derive' that also has a logback.xml file. Project 'derive' has a dependency on 'base'. When I lein trampoline repl on project 'derive', I get the following warning. 15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy] 15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml] 15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/home/stephen/Work/com.samedhi/derive/client/config/logback.xml] 15:34:30,067 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs multiple times on the
Re: function creation, partial or #()
Gosh darn... yes, that is what I want. That must be the only combination of things I didn't try! Thank you. On Sat, Aug 17, 2013 at 4:18 AM, Jay Fields j...@jayfields.com wrote: Sean, it sounds like you want (swap! some-a update-in [:k1 :k2] (fnil conj []) id) But that's based on some pretty limited context. On Friday, August 16, 2013, Sean Corfield wrote: On Fri, Aug 16, 2013 at 4:32 PM, Timothy Baldridge tbaldri...@gmail.com wrote: I'm just going to throw this out there, but I almost always consider using #() instead of (fn []) to be bad practice. I still use #() for anonymous single argument functions that are small, single forms, but I've started switching to (fn [..] ..) for anything even slightly more complex because, like you, I find having a named argument to be worth the extra typing, even if it is just a single letter, suggestive of the argument type. Today I found myself writing (fnil #(conj % id) []) a couple of times because (fnil (fn [v] (conj v id)) []) doesn't seem any clearer - but suggestions for nicer code are always welcome. It's part of (swap! some-atom update-in [:path :to :item] ...) if that helps :) Sean -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Current state of the art in Web deployment?
Hi folks, I'm starting work on a Clojure Web app and would like to get a sense for the current standard (if any) for deploying to production. In my case, I have an AWS Ubuntu instance, set up via Vagrant and Puppet, which mirrors some developer VMs. Datomic, leiningen etc. are running everywhere happily. After some prototyping and development, we are now getting to the stage where lein run and a Jetty server running from -main aren't going to cut it. I would like to get a sense for what people do now -- the story painted by Google / StackOverflow seems all over the place. Let's assume Heroku and Google App Engine are out of the picture, and that we are non-expert in terms of traditional Java approaches for Web apps (I'm coming mostly from a Python/Django background). So, what do all y'all do? What is a good lightweight but robust way to get a fairly simple Compojure/Ring app backed by Datomic facing the outside world? Not too worried about massive scalability at this point; simplicity will be a plus (am worried that e.g. Immutant / JBoss are too heavyweight). Not too active on this list so if my question can be improved, I'm happy to hear that as well. Thanks, awesome Clojure community!! John -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Do you like the Clojure syntax?
Hi, Random thought from a very tired person. :) Programmers manipulate tiny pieces of reality, so tiny that quantum effects come into play. [1] Many of us (unknowingly) train our visual senses to help us calculate these strange manipulations with less strain. Maybe if we train it on too narrow a range of notations, it's harder to extend this training to slightly perturbed ones. [2] Lisp + Paredit helps me train kinesthetic parts too. The effects are maybe too submerged for me to introspect [3], but Lisp is oddly close to things my hands manipulate in normal life. I commonly hold groups of things. Those things may be delimited by enclosing objects; between them may lie empty-looking space. (Of course, in daily life I'm not causing things to suddenly blink out of existence or be enclosed. But my body seems to adjust to the concept fine.) Lisp representation may just be symbolic, but manipulating it isn't only like text editing. It lends itself to structure editing. [4] BTW, this post isn't about Lisp is better than language X. If someone like likes X better than Lisp, then cheers. All the best, Tj [1] http://physics.stackexchange.com/questions/11567/is-quantum-physics-used-in-manufacturing-cpus [2] Given that Lisp syntax isn't merely aesthetic, but radically simplifies some things, it should often be worth the retraining. BTW, programming languages are artificial sorts of languages. Humans have enormous difficulty with them compared to natural language; if anyone claims that C-like languages are easier for humans to compute than Lisp, ask for scientific studies. Or simply email Chomsky and ask him. [3] It's likely good that we have limits to introspection, because otherwise we probably couldn't function as well. I suppose this is when people start using mystical terms like intuition. [4] I vaguely hear manipulating Java under Eclipse may be more advanced than Paredit, due to greater engineering effort. But this shouldn't affect the analysis. On Saturday, August 17, 2013 12:47:09 AM UTC+2, frye wrote: Oh thanks Steven. I've lately been thinking about human cognition, intelligence, etc. So boning up on my Chomsky, Kurzweil, and so on. Remember that the original lisp syntax only had a few core features: homoiconicity, first-class functions, recursion, garbage collection, etc. But from this core, the most advance language features have been easily added. Indeed, we're seeing this in real time, in Clojure: immutable data, lazy sequences, concurrent programming with STM, etc. Now, while theoretically possible, I don't think it's really feasible to implement many of these features in Cobol or Pascal - languages from the same era. Even Java has made a very clumsy attempt at closures, etc. But these other languages can't compete with the LISP approach, I think because of their syntax design. The human species still has an extremely limited understanding of how consciousness (ie cognition) works. My suspicion though, is that aspect's like the simplicity of lisp's syntax is what keeps it at the bleeding edge of computer science and our notions of computation. As limited as that is. Tim Washington Interruptsoftware.ca / Bkeeping.com On Fri, Aug 16, 2013 at 5:00 PM, Steven Degutis sbde...@gmail.comjavascript: wrote: Great point Tim. When I first realized that most problems and solutions are language-agnostic, I started downplaying the importance of syntax. But now I think they're like apples and oranges. Sure, semantics and syntax live together, but one's not more important than the other. They're both important to get right, for different reasons. For instance, while function calls in Ruby are (typically) semantically similar to in Clojure, destructuring arguments in Ruby is much more limited than in Clojure, and in Clojure it's much more easily readable as well as more powerful. This is only a syntax thing though, but it's a powerful player in the feature-set. On Fri, Aug 16, 2013 at 12:27 PM, Timothy Washington twas...@gmail.comjavascript: wrote: I think it's a mistake to discount the importance of syntax to a language. Human beings, as a species is heavily symbolic. Think of ancient cave paintings, to pictograms, to scripts. We use these symbols to communicate with each other, our outside world, and our abstract thoughts. Whether it's written / spoken language, or math or music notation, we need these symbols - it's a human thing. Dolphins or monkeys, while very intelligent, do not, by themselves, use these written symbols to communicate with each other. And I think it follows then, that the design of the syntax itself is important. It's certainly true that abstract concepts (of computation in this case) are the motive for using any given syntax. But the syntax impacts and facilitates the kinds of ideas we can have, the ease with which we can communicate them with each other,
Re: Current state of the art in Web deployment?
On 17 August 2013 21:52, John Jacobsen eigenhom...@gmail.com wrote: So, what do all y'all do? What is a good lightweight but robust way to get a fairly simple Compojure/Ring app backed by Datomic facing the outside world? Not too worried about massive scalability at this point; simplicity will be a plus (am worried that e.g. Immutant / JBoss are too heavyweight). One option is simply to write an upstart script that invokes 'lein ring server-headless' and sit an apache or nginx proxy in front of it. That's how my website is currently running. Alternatively, you could deploy your application as a war to tomcat or jetty. The upstart configuration, which is installed to /etc/init/cms.conf, can be found here: https://gist.github.com/ray1729/6258845 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: ANN swag a DSL for documenting Compojure routes using Swagger
Cool, let me know how it works out for you On Saturday, August 17, 2013 5:01:46 AM UTC+3, Casper Clausen wrote: Nice work. Looking forward to giving it a spin. On Thursday, August 15, 2013 12:13:11 PM UTC+2, ronen wrote: Swagger https://developers.helloreverb.com/swagger/ is a cool project for documenting Restful API's, Swag is a DSL that wraps Compojure routes enabling them to be listed and described automagically without the need of maintaining json https://github.com/narkisr/swag Feedback is welcome Ronen -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: What's your preference, partial or closures?
What do you mean by currying in this context? Is there a way to do this in clojure apart from using partial? On Saturday, August 17, 2013 10:04:23 AM UTC+10, Sean Corfield wrote: I went down the partial path for a long time but have moved more and more toward currying and closures lately as it seems to produce cleaner code - and this also seems to be the way Clojure/core have moved with the reducers library and other places...? Sean On Fri, Aug 16, 2013 at 3:00 PM, Alan Shaw node...@gmail.comjavascript: wrote: (defn newgrid [m initialize qi qj]... and then (let [init (partial newgrid m initialize)]... Or else: (defn newgrid [m initialize] (fn [qi qj]... and then (let [init (newgrid m initialize)]... -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: 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 javascript: 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 unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com javascript:. For more options, visit https://groups.google.com/groups/opt_out. -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: core.async - handling nils
My overall sense is that the convenience of using if-let directly in a few use cases doesn't justify making channels fall short of being able to send arbitrary values (nil specifically, and clearly boolean false can cause some problems too). I think it would be a much better design to have a sentinel value and a couple of specialised functions or macros that can detect / interact with it appropriately. With a sentinel value the key part of your if-recv code could just be something like: `(let [~name (! ~port)] (if (end-of-stream? ~name) ~else ~then I can see that wrappers for nil values could also work, but that seems to be a more complex solution (and also potentially with more overhead) than a sentinel value On Saturday, 17 August 2013 07:50:06 UTC+8, Brandon Bloom wrote: I ran into the other half of this problem: If you expect nils to signify closed channels, then you can't leverage the logically false nature of nil without excluding explicit boolean false values. Given the pleasant syntax of if-let / ! pairs, I reworked my early experiments to use if-recv which is defined as follows: (defmacro if-recv Reads from port, binding to name. Evaluates the then block if the read was successful. Evaluates the else block if the port was closed. ([[name port :as binding] then] `(if-recv ~binding ~then nil)) ([[name port] then else] `(let [~name (! ~port)] (if (nil? ~name) ~else ~then I've considered some alternative core.async designs, such as an additional done sentinel value, or a pair of quote/unquote operators (see reduced), but nothing seems as simple as just avoiding booleans and nils, as annoying as that is. I'd be curious to here what Rich team considered and how they're thinking about it. However, my expectation is that the nil approach won't change, since it's pretty much good enough. On Thursday, August 15, 2013 10:44:48 PM UTC-4, Mikera wrote: Hi all, I'm experimenting with core.async. Most of it is exceptionally good, but bit I'm finding it *very* inconvenient that nil can't be sent over channels. In particular, you can't pipe arbitrary Clojure sequences through channels (since sequences can contain nils). I see this as a pretty big design flaw given the ubiquity of sequences in Clojure code - it appears to imply that you can't easily compose channels with generic sequence-handling code without some pretty ugly special-case handling. Am I missing something? Is this a real problem for others too? If it is a design flaw, can it be fixed before the API gets locked down? -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: What's your preference, partial or closures?
On Sat, Aug 17, 2013 at 5:43 PM, yair yair@gmail.com wrote: What do you mean by currying in this context? Is there a way to do this in clojure apart from using partial? (defn some-func ([a b c] (process a b c)) ([a b] (fn [c] (some-func a b c))) ([a] (fn ([b] (fn [c] (some-func a b c))) ([b c] (some-func a b c) (some-func 1 2 3) ((some-func 1 2) 3) (((some-func 1) 2) 3) ((some-func 1) 2 3) -- Sean A Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ World Singles, LLC. -- http://worldsingles.com/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: core.async - handling nils
That's precisely the design followed by Magpie, described here: http://journal.stuffwithstuff.com/2013/04/17/well-done/ Parts 1 2 of that series are worth reading too. On Sat, Aug 17, 2013 at 8:48 PM, Mikera mike.r.anderson...@gmail.comwrote: My overall sense is that the convenience of using if-let directly in a few use cases doesn't justify making channels fall short of being able to send arbitrary values (nil specifically, and clearly boolean false can cause some problems too). I think it would be a much better design to have a sentinel value and a couple of specialised functions or macros that can detect / interact with it appropriately. With a sentinel value the key part of your if-recv code could just be something like: `(let [~name (! ~port)] (if (end-of-stream? ~name) ~else ~then I can see that wrappers for nil values could also work, but that seems to be a more complex solution (and also potentially with more overhead) than a sentinel value On Saturday, 17 August 2013 07:50:06 UTC+8, Brandon Bloom wrote: I ran into the other half of this problem: If you expect nils to signify closed channels, then you can't leverage the logically false nature of nil without excluding explicit boolean false values. Given the pleasant syntax of if-let / ! pairs, I reworked my early experiments to use if-recv which is defined as follows: (defmacro if-recv Reads from port, binding to name. Evaluates the then block if the read was successful. Evaluates the else block if the port was closed. ([[name port :as binding] then] `(if-recv ~binding ~then nil)) ([[name port] then else] `(let [~name (! ~port)] (if (nil? ~name) ~else ~then I've considered some alternative core.async designs, such as an additional done sentinel value, or a pair of quote/unquote operators (see reduced), but nothing seems as simple as just avoiding booleans and nils, as annoying as that is. I'd be curious to here what Rich team considered and how they're thinking about it. However, my expectation is that the nil approach won't change, since it's pretty much good enough. On Thursday, August 15, 2013 10:44:48 PM UTC-4, Mikera wrote: Hi all, I'm experimenting with core.async. Most of it is exceptionally good, but bit I'm finding it *very* inconvenient that nil can't be sent over channels. In particular, you can't pipe arbitrary Clojure sequences through channels (since sequences can contain nils). I see this as a pretty big design flaw given the ubiquity of sequences in Clojure code - it appears to imply that you can't easily compose channels with generic sequence-handling code without some pretty ugly special-case handling. Am I missing something? Is this a real problem for others too? If it is a design flaw, can it be fixed before the API gets locked down? -- -- 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 --- You received this message because you are subscribed to a topic in the Google Groups Clojure group. To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/pF9FEP7b77U/unsubscribe. To unsubscribe from this group and all its topics, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: core.async - handling nils
A sentinel value also prevents channels from being able to send/receive arbitrary values, without further wrapping. Sent from my iPhone On Aug 17, 2013, at 5:48 PM, Mikera mike.r.anderson...@gmail.com wrote: My overall sense is that the convenience of using if-let directly in a few use cases doesn't justify making channels fall short of being able to send arbitrary values (nil specifically, and clearly boolean false can cause some problems too). I think it would be a much better design to have a sentinel value and a couple of specialised functions or macros that can detect / interact with it appropriately. With a sentinel value the key part of your if-recv code could just be something like: `(let [~name (! ~port)] (if (end-of-stream? ~name) ~else ~then I can see that wrappers for nil values could also work, but that seems to be a more complex solution (and also potentially with more overhead) than a sentinel value On Saturday, 17 August 2013 07:50:06 UTC+8, Brandon Bloom wrote: I ran into the other half of this problem: If you expect nils to signify closed channels, then you can't leverage the logically false nature of nil without excluding explicit boolean false values. Given the pleasant syntax of if-let / ! pairs, I reworked my early experiments to use if-recv which is defined as follows: (defmacro if-recv Reads from port, binding to name. Evaluates the then block if the read was successful. Evaluates the else block if the port was closed. ([[name port :as binding] then] `(if-recv ~binding ~then nil)) ([[name port] then else] `(let [~name (! ~port)] (if (nil? ~name) ~else ~then I've considered some alternative core.async designs, such as an additional done sentinel value, or a pair of quote/unquote operators (see reduced), but nothing seems as simple as just avoiding booleans and nils, as annoying as that is. I'd be curious to here what Rich team considered and how they're thinking about it. However, my expectation is that the nil approach won't change, since it's pretty much good enough. On Thursday, August 15, 2013 10:44:48 PM UTC-4, Mikera wrote: Hi all, I'm experimenting with core.async. Most of it is exceptionally good, but bit I'm finding it *very* inconvenient that nil can't be sent over channels. In particular, you can't pipe arbitrary Clojure sequences through channels (since sequences can contain nils). I see this as a pretty big design flaw given the ubiquity of sequences in Clojure code - it appears to imply that you can't easily compose channels with generic sequence-handling code without some pretty ugly special-case handling. Am I missing something? Is this a real problem for others too? If it is a design flaw, can it be fixed before the API gets locked down? -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Model validation - exceptions as side-effects?
Leonardo, that's an interesting solution, thanks for writing it out and giving me some food for thought. My thought process was that at this point I have a pure API that either gets the right inputs or it simply does nothing. As in, no helping messages about what went wrong, no attempt to do recovery. Some claim that for security purposes errors encountered by the API should be as opaque as possible to leak few internal details, so that's vaguely the direction I'm going in at this point, even though you lose on the development front. I'd love to know your expert opinion on this, since you wrote Bouncer: say you're in the situation I listed above, where you don't care about nice error handling, you just want to give the caller a 400 if the input is incorrect. Would you still go the route where the validator function returns a list of errors? My concern is that now I have to have additional checks in place in my controller for whether the model save returned a list of errors, which will regardless ultimately result in a 400 status code. Thanks! (BTW, your blog is great, great content) On Friday, August 16, 2013 7:28:51 PM UTC-7, Leonardo Borges wrote: I would prefer not throwing an exception in the case of a validation. Say your validation function returns a vector or the first argument contains validation errors if any and the second contains the original map: (validate my-map) ;; returns [{:errors '(blah)} original-map] Then a neat way to write your function, taking advantage or core.match[1], would be this: (defn my-fn [my-map] (match (validate my-map) [{:errors errors} original-map] (handle-errors) [_ original-map] (save original-map))) This is my personal preference. It's concise, elegant and idiomatic in languages that support pattern matching. If you'd rather not use core.match for whatever reason, I'd still opt out of throwing an exception. The function would just need a little bit more code to simulate the behaviour above. [1]: https://github.com/clojure/core.match Leonardo Borges www.leonardoborges.com On Sat, Aug 17, 2013 at 12:08 PM, Alexandr Kurilin al...@kurilin.netjavascript: wrote: Let's hypothetically say I have a Ring application and I'm performing some validation on the input map I receive as part of a POST request. The validate function throws an exception if anything's wrong with the input. The exception is caught in the middleware and turned into a 400 code response. I could do either: (- input validate save) or I could do: (do (validate input) (save input)) The former doesn't really buy me anything, since a new version of input would never be returned by validate. It is however side-effect free in a way? The latter is probably less idiomatic, but makes it obvious that input is not changing as part of the evaluation. What would be the more elegant way of handling this? Is the do block approach somehow inferior? Thanks! -- -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: 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 javascript: 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 unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com javascript:. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Current state of the art in Web deployment?
On Sun, Aug 18, 2013 at 6:52 AM, John Jacobsen eigenhom...@gmail.comwrote: After some prototyping and development, we are now getting to the stage where lein run and a Jetty server running from -main aren't going to cut it. At the risk of asking a dumb question, but being quite new to Clojure, I don't mind - why do you say they won't cut it? Mark -- E: mark.man...@gmail.com T: http://www.twitter.com/neurotic W: www.compoundtheory.com 2 Devs from Down Under Podcast http://www.2ddu.com/ -- -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.