Re: is PG's imperative outside-in advice any good?
For those who use clojure.tools.logging, there's also the handy spy function. On Tuesday, October 15, 2013 6:41:38 PM UTC-7, dgrnbrg wrote: If this is something you do often, spyscope is a library I wrote to simplify this sort of investigation. You can print an expression by writing #spy/d in front of it. For more information, you can read at https://github.com/dgrnbrg/spyscope On Tuesday, October 15, 2013 10:13:58 AM UTC-4, Brian Hurt wrote: Lifting subexpressions up into lets is actually something I do a lot- for one very important reason: it lets me insert print statements (or logging statements) showing the value of the subexpression. So I'll do; (let [ x (subexpression) ] (main-expression)) because it lets me do: (let [ x (subexpression) ] (println The value of x is x) (main-expression)) If fact, a lot of times I'll do; (let [ x (subexpression) res (main-expression) ] res) because it lets me do: (let [ x (subexpression) _ (println The value of x is x) res (main-expression) ] (println The value of the whole expression is res) res) This is of great value in debugging. Brian On Tue, Oct 15, 2013 at 9:56 AM, Mikera mike.r.an...@gmail.com wrote: I certainly prefer giving names to intermediate results with a let block: having good names and breaking the computation up into logical chunks makes the code much easier to understand and maintain when you come back to it later. PG's example though is bad for different reasons - this is actually mutating variables in an imperative style, which is definitely bad style - both in Lisp and Clojure I think. The Clojure equivalent would be to use atoms (or vars) and mutating them. let on its own is purely functional, and doesn't have this problem. On Tuesday, 15 October 2013 20:29:29 UTC+8, Daniel Higginbotham wrote: I've been going through On Lisp by Paul Graham and on page 33 he recommends against performing intermediate bindings. Does this advice hold for Clojure? Here are a couple examples: ;; Common Lisp (from the book) (defun bad (x) (let (y sqr) (setq y (car x)) (setq sqr (expt y 2)) (list 'a sqr))) (defun good (x) (list 'a (expt (car x) 2))) ;; Clojure (defn bad [x] (let [y (first x) sqr (expt y 2)] (list 'a sqr))) (defn good [x] (list 'a (expt (first x) 2))) Paul Graham explains: The final result is shorter than what we began with, and easier to understand. In the original code, we’re faced with the final expression (list 'a sqr), and it’s not immediately clear where the value of sqr comes from. Now the source of the return value is laid out for us like a road map. The example in this section was a short one, but the technique scales up. Indeed, it becomes more valuable as it is applied to larger functions. In clojure you can't do setq of course but I find myself going against this advice all the time, and I find that it's more important to do so when working with larger functions. I think introducing names makes code clearer. Here's an example from my own code: (defn create-topic [params] (let [params (merge params (db/tempids :topic-id :post-id :watch-id)) topic (remove-nils-from-map (c/mapify params mr/topic-txdata)) watch (c/mapify params mr/watch-txdata) post (c/mapify params mr/post-txdata)] {:result (db/t [topic post watch]) :tempid (:topic-id params)})) To my mind, creating bindings for topic, watch, and post makes the code easier to understand. When you get to (db/t [topic post watch]) you don't have to deal with as much visual noise to understand exactly what's going into the transaction. So, is PG's advice any good? Thanks! Daniel -- -- 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 --- 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. 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
Re: is PG's imperative outside-in advice any good?
In CL, `let*` works like Clojure's `let`, in that both allow you to bind later variables to valued calculated from earlier ones. (CL's `let` only allows references to things defined before entering the `let`.) A couple of years ago I was hacking on some CL code originally written by someone else, with a lot of `let*`s in it. I started adding bindings, and them more, and after a while I just could not make it work. The order of bindings was crucial, and the right hand sides were referring to multiple variables bound elsewhere in the `let*`. It was driving me crazy. I realized that the whole thing I'd created was an instance of bad coding style.I just pulled things apart and put the code into separate functions that called each other. And I replaced all of my `do*`s (loops with bindings that can refer to each other) with `mapcar` or `mapc` (like Clojure's `map`). Much clearer. I now try to avoid `let*` as much as possible in CL, and when I use it, I make sure that I keep things simple. I'm just learning Clojure. I'm not going to avoid `let`, but I will try to make sure that I use it carefully. I agree with other posters here that sometimes code is clearer and easier to understand if it's broken into sequential bindings, but it depends. I think that often it's better to use a series of separate function calls instead of a big `let`. I would say that for me, a good rule of thumb is that a `let` should bind no more than four or five variables, maximum, and that if there are more variables, their rhs's should usually refer only to the variable defined on the previous line. Otherwise it's too hard to keep track of the dependencies. Maybe the right thing to say is: Follow PG's rule, except when it's better to break it. And then keep it simple. Those aren't rules that anyone else has to follow, of course. Do what works for you. This is how I think about it. On Tuesday, October 15, 2013 7:29:29 AM UTC-5, Daniel Higginbotham wrote: I've been going through On Lisp by Paul Graham and on page 33 he recommends against performing intermediate bindings. Does this advice hold for Clojure? Here are a couple examples: ;; Common Lisp (from the book) (defun bad (x) (let (y sqr) (setq y (car x)) (setq sqr (expt y 2)) (list 'a sqr))) (defun good (x) (list 'a (expt (car x) 2))) ;; Clojure (defn bad [x] (let [y (first x) sqr (expt y 2)] (list 'a sqr))) (defn good [x] (list 'a (expt (first x) 2))) Paul Graham explains: The final result is shorter than what we began with, and easier to understand. In the original code, we’re faced with the final expression (list 'a sqr), and it’s not immediately clear where the value of sqr comes from. Now the source of the return value is laid out for us like a road map. The example in this section was a short one, but the technique scales up. Indeed, it becomes more valuable as it is applied to larger functions. In clojure you can't do setq of course but I find myself going against this advice all the time, and I find that it's more important to do so when working with larger functions. I think introducing names makes code clearer. Here's an example from my own code: (defn create-topic [params] (let [params (merge params (db/tempids :topic-id :post-id :watch-id)) topic (remove-nils-from-map (c/mapify params mr/topic-txdata)) watch (c/mapify params mr/watch-txdata) post (c/mapify params mr/post-txdata)] {:result (db/t [topic post watch]) :tempid (:topic-id params)})) To my mind, creating bindings for topic, watch, and post makes the code easier to understand. When you get to (db/t [topic post watch]) you don't have to deal with as much visual noise to understand exactly what's going into the transaction. So, is PG's advice any good? Thanks! Daniel -- -- 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.
is PG's imperative outside-in advice any good?
I've been going through On Lisp by Paul Graham and on page 33 he recommends against performing intermediate bindings. Does this advice hold for Clojure? Here are a couple examples: ;; Common Lisp (from the book) (defun bad (x) (let (y sqr) (setq y (car x)) (setq sqr (expt y 2)) (list 'a sqr))) (defun good (x) (list 'a (expt (car x) 2))) ;; Clojure (defn bad [x] (let [y (first x) sqr (expt y 2)] (list 'a sqr))) (defn good [x] (list 'a (expt (first x) 2))) Paul Graham explains: The final result is shorter than what we began with, and easier to understand. In the original code, we’re faced with the final expression (list 'a sqr), and it’s not immediately clear where the value of sqr comes from. Now the source of the return value is laid out for us like a road map. The example in this section was a short one, but the technique scales up. Indeed, it becomes more valuable as it is applied to larger functions. In clojure you can't do setq of course but I find myself going against this advice all the time, and I find that it's more important to do so when working with larger functions. I think introducing names makes code clearer. Here's an example from my own code: (defn create-topic [params] (let [params (merge params (db/tempids :topic-id :post-id :watch-id)) topic (remove-nils-from-map (c/mapify params mr/topic-txdata)) watch (c/mapify params mr/watch-txdata) post (c/mapify params mr/post-txdata)] {:result (db/t [topic post watch]) :tempid (:topic-id params)})) To my mind, creating bindings for topic, watch, and post makes the code easier to understand. When you get to (db/t [topic post watch]) you don't have to deal with as much visual noise to understand exactly what's going into the transaction. So, is PG's advice any good? Thanks! Daniel -- -- 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: is PG's imperative outside-in advice any good?
Lifting subexpressions up into lets is actually something I do a lot- for one very important reason: it lets me insert print statements (or logging statements) showing the value of the subexpression. So I'll do; (let [ x (subexpression) ] (main-expression)) because it lets me do: (let [ x (subexpression) ] (println The value of x is x) (main-expression)) If fact, a lot of times I'll do; (let [ x (subexpression) res (main-expression) ] res) because it lets me do: (let [ x (subexpression) _ (println The value of x is x) res (main-expression) ] (println The value of the whole expression is res) res) This is of great value in debugging. Brian On Tue, Oct 15, 2013 at 9:56 AM, Mikera mike.r.anderson...@gmail.comwrote: I certainly prefer giving names to intermediate results with a let block: having good names and breaking the computation up into logical chunks makes the code much easier to understand and maintain when you come back to it later. PG's example though is bad for different reasons - this is actually mutating variables in an imperative style, which is definitely bad style - both in Lisp and Clojure I think. The Clojure equivalent would be to use atoms (or vars) and mutating them. let on its own is purely functional, and doesn't have this problem. On Tuesday, 15 October 2013 20:29:29 UTC+8, Daniel Higginbotham wrote: I've been going through On Lisp by Paul Graham and on page 33 he recommends against performing intermediate bindings. Does this advice hold for Clojure? Here are a couple examples: ;; Common Lisp (from the book) (defun bad (x) (let (y sqr) (setq y (car x)) (setq sqr (expt y 2)) (list 'a sqr))) (defun good (x) (list 'a (expt (car x) 2))) ;; Clojure (defn bad [x] (let [y (first x) sqr (expt y 2)] (list 'a sqr))) (defn good [x] (list 'a (expt (first x) 2))) Paul Graham explains: The final result is shorter than what we began with, and easier to understand. In the original code, we’re faced with the final expression (list 'a sqr), and it’s not immediately clear where the value of sqr comes from. Now the source of the return value is laid out for us like a road map. The example in this section was a short one, but the technique scales up. Indeed, it becomes more valuable as it is applied to larger functions. In clojure you can't do setq of course but I find myself going against this advice all the time, and I find that it's more important to do so when working with larger functions. I think introducing names makes code clearer. Here's an example from my own code: (defn create-topic [params] (let [params (merge params (db/tempids :topic-id :post-id :watch-id)) topic (remove-nils-from-map (c/mapify params mr/topic-txdata)) watch (c/mapify params mr/watch-txdata) post (c/mapify params mr/post-txdata)] {:result (db/t [topic post watch]) :tempid (:topic-id params)})) To my mind, creating bindings for topic, watch, and post makes the code easier to understand. When you get to (db/t [topic post watch]) you don't have to deal with as much visual noise to understand exactly what's going into the transaction. So, is PG's advice any good? Thanks! Daniel -- -- 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: is PG's imperative outside-in advice any good?
if a programming language doesn't have something like 'where', then i am sad. http://stackoverflow.com/questions/4362328/haskell-where-vs-let -- -- 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: is PG's imperative outside-in advice any good?
I and some of my coworkers do tend to avoid `let` unless in this particular case you especially want to emphasize the name of something unobvious. OFten I'd prefer to pull out a new function over using let, or inline the binding for readability *improvement*. On Tue, Oct 15, 2013 at 8:18 AM, Raoul Duke rao...@gmail.com wrote: if a programming language doesn't have something like 'where', then i am sad. http://stackoverflow.com/questions/4362328/haskell-where-vs-let -- -- 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: is PG's imperative outside-in advice any good?
Yeah, I found when I first got started with Clojure I tended to use let for intermediate named results but over time I've moved to using small, private top-level functions instead because I want to focus on the names of the _functionality_ rather than the names of intermediate _data_. I still use let for some things but nowhere near as much as I used to. One construct using let that I see in my code quite a bit that I haven't figured out a cleaner way to express: (let [x (some-expression)] (if (p x) (f x) (g x))) I get tempted to write a utility function for it but I haven't come up with a good name for it :) Sean On Tue, Oct 15, 2013 at 9:00 AM, Alex Baranosky alexander.barano...@gmail.com wrote: I and some of my coworkers do tend to avoid `let` unless in this particular case you especially want to emphasize the name of something unobvious. OFten I'd prefer to pull out a new function over using let, or inline the binding for readability *improvement*. On Tue, Oct 15, 2013 at 8:18 AM, Raoul Duke rao...@gmail.com wrote: if a programming language doesn't have something like 'where', then i am sad. http://stackoverflow.com/questions/4362328/haskell-where-vs-let -- -- 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.
Re: is PG's imperative outside-in advice any good?
How looks this? (defn conditional [x condition consequent alternative] (if (condition x) (consequent x) (alternative x (conditional (some-expression) p f g) Am 15.10.2013 19:02, schrieb Sean Corfield: Yeah, I found when I first got started with Clojure I tended to use let for intermediate named results but over time I've moved to using small, private top-level functions instead because I want to focus on the names of the _functionality_ rather than the names of intermediate _data_. I still use let for some things but nowhere near as much as I used to. One construct using let that I see in my code quite a bit that I haven't figured out a cleaner way to express: (let [x (some-expression)] (if (p x) (f x) (g x))) I get tempted to write a utility function for it but I haven't come up with a good name for it :) Sean On Tue, Oct 15, 2013 at 9:00 AM, Alex Baranosky alexander.barano...@gmail.com wrote: I and some of my coworkers do tend to avoid `let` unless in this particular case you especially want to emphasize the name of something unobvious. OFten I'd prefer to pull out a new function over using let, or inline the binding for readability *improvement*. On Tue, Oct 15, 2013 at 8:18 AM, Raoul Duke rao...@gmail.com wrote: if a programming language doesn't have something like 'where', then i am sad. http://stackoverflow.com/questions/4362328/haskell-where-vs-let -- -- 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. -- -- 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: is PG's imperative outside-in advice any good?
Sean, The case you listed is where let binding becomes important so as to not perform duplicate evaluation. That is one place the utility of let stands out along with its scope. For example Without let bindings: (if (p (some-expression)) (f (some-expression)) (g (some-expression)) introduces duplicate evaluation. I see the utility of let more in such scenarios. Whereas in the original PGs example that is not the case, and debate on that stands. On Tue, Oct 15, 2013 at 10:02 AM, Sean Corfield seancorfi...@gmail.comwrote: Yeah, I found when I first got started with Clojure I tended to use let for intermediate named results but over time I've moved to using small, private top-level functions instead because I want to focus on the names of the _functionality_ rather than the names of intermediate _data_. I still use let for some things but nowhere near as much as I used to. One construct using let that I see in my code quite a bit that I haven't figured out a cleaner way to express: (let [x (some-expression)] (if (p x) (f x) (g x))) I get tempted to write a utility function for it but I haven't come up with a good name for it :) Sean On Tue, Oct 15, 2013 at 9:00 AM, Alex Baranosky alexander.barano...@gmail.com wrote: I and some of my coworkers do tend to avoid `let` unless in this particular case you especially want to emphasize the name of something unobvious. OFten I'd prefer to pull out a new function over using let, or inline the binding for readability *improvement*. On Tue, Oct 15, 2013 at 8:18 AM, Raoul Duke rao...@gmail.com wrote: if a programming language doesn't have something like 'where', then i am sad. http://stackoverflow.com/questions/4362328/haskell-where-vs-let -- -- 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. -- -- 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: is PG's imperative outside-in advice any good?
I know how to write it but I just don't like that name (or any other I've come up with yet). And I'd probably put the `x` as the last argument and provide a curried version. On Tue, Oct 15, 2013 at 10:13 AM, Marcus Lindner marcus.goldritter.lind...@gmail.com wrote: How looks this? (defn conditional [x condition consequent alternative] (if (condition x) (consequent x) (alternative x (conditional (some-expression) p f g) Am 15.10.2013 19:02, schrieb Sean Corfield: Yeah, I found when I first got started with Clojure I tended to use let for intermediate named results but over time I've moved to using small, private top-level functions instead because I want to focus on the names of the _functionality_ rather than the names of intermediate _data_. I still use let for some things but nowhere near as much as I used to. One construct using let that I see in my code quite a bit that I haven't figured out a cleaner way to express: (let [x (some-expression)] (if (p x) (f x) (g x))) I get tempted to write a utility function for it but I haven't come up with a good name for it :) Sean On Tue, Oct 15, 2013 at 9:00 AM, Alex Baranosky alexander.barano...@gmail.com wrote: I and some of my coworkers do tend to avoid `let` unless in this particular case you especially want to emphasize the name of something unobvious. OFten I'd prefer to pull out a new function over using let, or inline the binding for readability *improvement*. On Tue, Oct 15, 2013 at 8:18 AM, Raoul Duke rao...@gmail.com wrote: if a programming language doesn't have something like 'where', then i am sad. http://stackoverflow.com/questions/4362328/haskell-where-vs-let -- -- 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. -- -- 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.
Re: is PG's imperative outside-in advice any good?
On Tue, Oct 15, 2013 at 10:15 AM, Guru Devanla grd...@gmail.com wrote: The case you listed is where let binding becomes important so as to not perform duplicate evaluation. That is one place the utility of let stands out along with its scope. Yup, exactly. I just see it often enough that I feel that it should be codified somehow... -- 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: is PG's imperative outside-in advice any good?
On 15/10/13 18:02, Sean Corfield wrote: One construct using let that I see in my code quite a bit that I haven't figured out a cleaner way to express: (let [x (some-expression)] (if (p x) (f x) (g x))) wasn't cond- designed exactly for that? (let [x (some-expression)] (cond- x (p x) f ((comlpement p) x) g))) Jim -- -- 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: is PG's imperative outside-in advice any good?
On Tue, Oct 15, 2013 at 10:19 AM, Jim - FooBar(); jimpil1...@gmail.com wrote: wasn't cond- designed exactly for that? (let [x (some-expression)] (cond- x (p x) f ((comlpement p) x) g))) That's uglier than the if :) Sometimes I wish there was a variant of cond- that took functions instead of boolean expressions and threaded the expression thru those (just to wander further off-topic)... -- 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: is PG's imperative outside-in advice any good?
What about let-some-expression-if-then-else? From: clojure@googlegroups.com [clojure@googlegroups.com] on behalf of Sean Corfield [seancorfi...@gmail.com] Sent: 15 October 2013 18:02 To: clojure@googlegroups.com Subject: Re: is PG's imperative outside-in advice any good? Yeah, I found when I first got started with Clojure I tended to use let for intermediate named results but over time I've moved to using small, private top-level functions instead because I want to focus on the names of the _functionality_ rather than the names of intermediate _data_. I still use let for some things but nowhere near as much as I used to. One construct using let that I see in my code quite a bit that I haven't figured out a cleaner way to express: (let [x (some-expression)] (if (p x) (f x) (g x))) I get tempted to write a utility function for it but I haven't come up with a good name for it :) Sean On Tue, Oct 15, 2013 at 9:00 AM, Alex Baranosky alexander.barano...@gmail.com wrote: I and some of my coworkers do tend to avoid `let` unless in this particular case you especially want to emphasize the name of something unobvious. OFten I'd prefer to pull out a new function over using let, or inline the binding for readability *improvement*. On Tue, Oct 15, 2013 at 8:18 AM, Raoul Duke rao...@gmail.com wrote: if a programming language doesn't have something like 'where', then i am sad. http://stackoverflow.com/questions/4362328/haskell-where-vs-let -- -- 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. -- -- 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: is PG's imperative outside-in advice any good?
On Tue, Oct 15, 2013 at 10:48 AM, Sean Corfield seancorfi...@gmail.comwrote: On Tue, Oct 15, 2013 at 10:19 AM, Jim - FooBar(); jimpil1...@gmail.com wrote: wasn't cond- designed exactly for that? (let [x (some-expression)] (cond- x (p x) f ((comlpement p) x) g))) That's uglier than the if :) Also less efficient, since it may require evaluating (p x) twice. If it were me, I'd use something like this: (defn either Return a function that takes one argument, x, and returns (f x) if (p x) is truthy and (g x) otherwise. [p f g] (fn [x] (if (p x) (f x) (g x -- Ben Wolfson Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure. [Larousse, Drink entry] -- -- 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: is PG's imperative outside-in advice any good?
On 2013-10-15, at 8:29 AM, Daniel Higginbotham nonrecurs...@gmail.com wrote: I've been going through On Lisp by Paul Graham and on page 33 he recommends against performing intermediate bindings. Does this advice hold for Clojure? Here are a couple examples: ;; Common Lisp (from the book) (defun bad (x) (let (y sqr) (setq y (car x)) (setq sqr (expt y 2)) (list 'a sqr))) (defun good (x) (list 'a (expt (car x) 2))) ;; Clojure (defn bad [x] (let [y (first x) sqr (expt y 2)] (list 'a sqr))) (defn good [x] (list 'a (expt (first x) 2))) The closest I can think of to the bad CL code in Clojure would be something like: (defn bad-clojure [x] (let [v (first x) v (Math/pow v 2) v (list 'a v)] v)) I don't think anyone at all would find either the bad CL or Clojure code okay. This is more of an admonition to not be an idiot :-) Your Clojure code is equivalent to the following CL code: (defun good2 (x) (let* ((y (car x)) (sqr (expt y 2))) (list 'a sqr))) There's nothing wrong with writing code that way, it's functional and clear. What you're doing with this style of writing is introducing intermediate named values. Sometimes those just clutter up the code, sometimes they clarify. Use your own good taste. You'd do the same thing in Haskell, but I'd use a where clause. Paul Graham explains: The final result is shorter than what we began with, and easier to understand. In the original code, we’re faced with the final expression (list 'a sqr), and it’s not immediately clear where the value of sqr comes from. Now the source of the return value is laid out for us like a road map. The example in this section was a short one, but the technique scales up. Indeed, it becomes more valuable as it is applied to larger functions. Yes, in the bad CL code you don't know where the value of sqr comes from and the problem gets much worse as the code gets longer. This is the problem with imperative code in general. You don't have that problem in either Clojure or the 'good2' CL program. In clojure you can't do setq of course but I find myself going against this advice all the time He's not talking about intermediate names for values, he's talking about imperative assignments using setq, setf, and friends. Clojure's nearest equivalent, that I can think of, is shadowing in a let statement, and I think you'll find this is frowned upon. So, is PG's advice any good? Yup. Cheers, Bob Thanks! Daniel -- -- 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: is PG's imperative outside-in advice any good?
Thanks for all the responses! This discussion will definitely help me write better code. This was especially helpful: over time I've moved to using small, private top-level functions instead because I want to focus on the names of the _functionality_ rather than the names of intermediate _data_ As was this: because it lets me do: (let [ x (subexpression) _ (println The value of x is x) res (main-expression) ] (println The value of the whole expression is res) res) Thanks! Daniel -- -- 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.