Re: Comments on first function
Hi, Good inital effort. Only a couple of things to comment on: - You're not closing the stream after you're done with it This is a very common bug and for that reason clojure provides a macro - with-open - that takes care of closing the resource for you. - As you're using a string as the accumulator, you're creating a new string object at each iteration: A better approach might be using a StringBuffer to accumulate the result without wasteful object allocation. In fact, both of these points are addressed by a core clojure function called 'slurp'. Here's its source and sample usage: (defn slurp ([f opts] (let [opts (normalize-slurp-opts opts) sb (StringBuilder.)] (with-open [#^java.io.Reader r (apply jio/reader f opts)] (loop [c (.read r)] (if (neg? c) (str sb) (do (.append sb (char c)) (recur (.read r) (println (slurp http://google.com;)) You can read more about with-open in this link: http://clojuredocs.org/clojure_core/clojure.core/with-open Cheers, Leonardo Borges www.leonardoborges.com On Mon, Nov 18, 2013 at 2:00 PM, jskdlfj...@outlook.com wrote: Hi everyone, I'm new to Clojure, and after a lot of reading I wrote a couple of functions. They are working and doing what they are supposed to, but I was wondering if the way I wrote the functions was optimal and if I made any conceptual errors which advanced programmers avoid. Basically: Are they what they call the clojure way? (defn download-source [url] (let [stream (java.io.BufferedReader. (java.io.InputStreamReader. (.. (java.net.URL. url) openStream)))] (loop [b (.readLine stream), acc ] (if (= b nil) acc (recur (.readLine stream) (str acc b)) (println (download-source http://google.com;)) This function for example downloads the source of a webpage and returns it as a string. Could this have been written in a better way? I want to get a feeling of what is considered good practice/design in clojure. Nice Regards -- -- 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.
Comments on first function
Hi everyone, I'm new to Clojure, and after a lot of reading I wrote a couple of functions. They are working and doing what they are supposed to, but I was wondering if the way I wrote the functions was optimal and if I made any conceptual errors which advanced programmers avoid. Basically: Are they what they call the clojure way? (defn download-source [url] (let [stream (java.io.BufferedReader. (java.io.InputStreamReader. (.. (java.net.URL. url) openStream)))] (loop [b (.readLine stream), acc ] (if (= b nil) acc (recur (.readLine stream) (str acc b)) (println (download-source http://google.com;)) This function for example downloads the source of a webpage and returns it as a string. Could this have been written in a better way? I want to get a feeling of what is considered good practice/design in clojure. Nice Regards -- -- 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: First function
Thanks for all the excellent, concise advice! For code and idiomatic improvements, from these messages I have the following - For order 1 access use vector - Use subvectors for efficient partitioning - Case/compare is concise, powerful and readable - Use seq idiom to proceed or return nil - Two spaces for indentation - Indentation: parameters at same level, flow control at next level - Line up trailing parens - Dash, not underscore - =, unless data is integer and we have performance measurements that demand == - inc more idiomatic than (+ number 1) Awesome advice, getting into this has been totally great. Brody On Thu, Oct 21, 2010 at 11:50 AM, Jürgen Hötzel juer...@hoetzel.infowrote: 2010/10/21 Brody Berg brodyb...@gmail.com: (defn binary-search Search sorted list for target using binary search technique Binary search is only useful on indexed data types like Clojure Vectors. ([m_list target] (if (empty? m_list) false (binary-search m_list 0 (- (count m_list) 1) target)) ) ([m_list m_left m_right target] Because Vectors are persistent you can create Sub-Vectors instead of keeping tracking offsets. (let [gap (- m_right m_left)] (if (= 0 gap) (if (== (nth m_list m_left) target) (nth m_list m_left) false No need for explicit false. Using case/compare you can also replace multiple tests by a single comparison and constant time lookup: (defn binary-search [v x] (if (seq v) (let [half (quot (count v) 2) middle (v half)] (case (compare middle x) -1 (recur (subvec v (inc half)) x) 1 (recur (subvec v 0 half) x) true Jürgen -- 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.comclojure%2bunsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
First function
Hey, Not sure if this is the right place for this - but I just wrote my first function in Clojure and wanted to make sure I am on the right track idiomatically and making full use of the language etc. I have been able to build/run and unit test this so that's all fine. Take a look at the below and let me know if you have any suggestions. Thanks in advance! Brody (defn binary-search Search sorted list for target using binary search technique ([m_list target] (if (empty? m_list) false (binary-search m_list 0 (- (count m_list) 1) target)) ) ([m_list m_left m_right target] (let [gap (- m_right m_left)] (if (= 0 gap) (if (== (nth m_list m_left) target) (nth m_list m_left) false ) (let [middle (+ m_left (quot gap 2))] (if (== (nth m_list middle) target) (nth m_list middle) (if ( target (nth m_list middle)) (recur m_list m_left (- middle 1) target) (recur m_list (+ middle 1) m_right target) ) ) ) ) ) ) ) -- 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: First function
On Oct 21, 2010, at 3:28 AM, Brody Berg wrote: (if (empty? m_list) false (binary-search m_list 0 (- (count m_list) 1) target)) Assuming that returning nil is OK in case of the target not being present, you can replace this with (when (seq m_list) (binary-search ...)). (if (== (nth m_list m_left) target) (nth m_list m_left) false Can similarly replace with (when (== (nth m_list m_left) target) target). But why are you returning the target value on success? Presumably the caller knows what that value is, and it makes your function awkward to use if target is false or nil. Why not return either the target's index, or just 'true' if you don't need that? Also, can you assume m_list is a vector, or if not, make it into one in your helper body? That would let you write (m-list n) instead of (nth m-list n), and would guarantee constant-time performance when you do it. (- middle 1) (+ middle 1) Can replace with (dec middle) and (inc middle), respectively. Lastly, as a matter of style: Lisp users generally hate trailing parentheses. It's extremely common to simply collapse them onto the previous line. Your editor should be able to do the grunt-work of helping you balance them, and they pretty much disappear after a while. -- 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: First function
On Oct 21, 2010, at 3:28 AM, Brody Berg wrote: (if (== (nth m_list m_left) target) Forgot to mention: you should use = instead of == unless you're sure you will only ever get numeric arguments *and* profiling tells you that = is a performance bottleneck. -- 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: First function
You should close the parenthesis all in one line: (defn binary-search Search sorted list for target using binary search technique ([m_list target] (if (empty? m_list) false (binary-search m_list 0 (- (count m_list) 1) target))) ([m_list m_left m_right target] (let [gap (- m_right m_left)] (if (= 0 gap) (if (== (nth m_list m_left) target) (nth m_list m_left) false) (let [middle (+ m_left (quot gap 2))] (if (== (nth m_list middle) target) (nth m_list middle) (if ( target (nth m_list middle)) (recur m_list m_left (- middle 1) target) (recur m_list (+ middle 1) m_right target It safes some space ;) -- 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: First function
To expand on this: 1. It's better to use when (or when-not) if one branch of your if is just a false value. E.g. you could replace (if (empty? x) false (whatever)) with (when-not (empty? x)). However... 2. Don't use empty? if you can help it! The idiomatic way to test whether a collection has any items in it is to use (seq coll), which returns nil if coll is empty, or a seq of the collection otherwise. So then your if reduces to the very common (when (seq x) (whatever)) 3. Lisp paren style is very different from C-like brace style. There are a few rebels out there who do things differently, and if you're the only one using the code, feel free. However, you'll get better at reading and writing Lisp code if you let the indentation be your guide. Parentheses are just there for the compiler; indentation is so *you* know what's going on. There should never (I'm sure someone can think of an exception) be whitespace of any kind immediately preceding a closing bracket. Songoku's sample uses them in the traditional style. 4. The usual indentation is two spaces, not four. 5. This last one you might already know, but it's hard to tell because you used indents of four. Typically you indent flow control sorts of statements with the standard indent, like: (when (seq x) (whatever)) But other sorts of multi-form constructs you usually line the arguments up with each other: this helps a lot with tip (3), because it means you don't need the parens to see what's up. Like so (don't worry about what the functions do, it's just an indentation example): (map #(+ %2 (/ 2 %1)) (filter even? (range 4 99)) (drop-while #( 1000) (range))) This way you can tell at a glance what forms fit where, even in my nonsensical example where it's not clear what the overall purpose is. On Oct 21, 4:12 am, Michael Gardner gardne...@gmail.com wrote: On Oct 21, 2010, at 3:28 AM, Brody Berg wrote: (if (empty? m_list) false (binary-search m_list 0 (- (count m_list) 1) target)) Assuming that returning nil is OK in case of the target not being present, you can replace this with (when (seq m_list) (binary-search ...)). (if (== (nth m_list m_left) target) (nth m_list m_left) false Can similarly replace with (when (== (nth m_list m_left) target) target). But why are you returning the target value on success? Presumably the caller knows what that value is, and it makes your function awkward to use if target is false or nil. Why not return either the target's index, or just 'true' if you don't need that? Also, can you assume m_list is a vector, or if not, make it into one in your helper body? That would let you write (m-list n) instead of (nth m-list n), and would guarantee constant-time performance when you do it. (- middle 1) (+ middle 1) Can replace with (dec middle) and (inc middle), respectively. Lastly, as a matter of style: Lisp users generally hate trailing parentheses. It's extremely common to simply collapse them onto the previous line. Your editor should be able to do the grunt-work of helping you balance them, and they pretty much disappear after a while. -- 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: First function
2010/10/21 Brody Berg brodyb...@gmail.com: (defn binary-search Search sorted list for target using binary search technique Binary search is only useful on indexed data types like Clojure Vectors. ([m_list target] (if (empty? m_list) false (binary-search m_list 0 (- (count m_list) 1) target)) ) ([m_list m_left m_right target] Because Vectors are persistent you can create Sub-Vectors instead of keeping tracking offsets. (let [gap (- m_right m_left)] (if (= 0 gap) (if (== (nth m_list m_left) target) (nth m_list m_left) false No need for explicit false. Using case/compare you can also replace multiple tests by a single comparison and constant time lookup: (defn binary-search [v x] (if (seq v) (let [half (quot (count v) 2) middle (v half)] (case (compare middle x) -1 (recur (subvec v (inc half)) x) 1 (recur (subvec v 0 half) x) true Jürgen -- 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: Remove-first function
I expanded on this theme in a blog post: http://programming-puzzler.blogspot.com/2010/07/translating-code-from-python-and-scheme.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
Re: Remove-first function
@Randy Hudson Really like that solution. @Mark Engelberg Thanks for the explanation On Jul 25, 4:33 am, ataggart alex.tagg...@gmail.com wrote: To add one small addendum to Mark's excellent comment, if you use lazy- seq then you don't need to worry about the nil from when On Jul 24, 12:01 pm, Mark Engelberg mark.engelb...@gmail.com wrote: On Sat, Jul 24, 2010 at 11:45 AM, Mark Engelberg mark.engelb...@gmail.com wrote: The simplest translation is to wrap a lazy-seq around the last line to avoid the stack overflows. Just to clarify, there are at least three reasonable places to place the call to lazy-seq. You can put lazy-seq around the full body of the function. You can place it around the cons. You can place it around the recursive call to scheme-remove-first. Each choice results in slightly different laziness behavior, i.e., when various elements are computed, but the overall semantics of the sequence remains the same and stack overflows will be avoided. Placing the lazy-seq around the recursive function call will cause scheme-remove-first to compute the first element right away, and delay the rest. Placing the lazy-seq around the full body will prevent any computation until it is asked for by a consumer. Placing the lazy-seq around the cons results in in immediate behavior for the nil and removable-item-at-front-of-list case, and delayed behavior otherwise. All are acceptable choices, but preferences vary. Probably placing lazy-seq around the full body is the most common style you'll see in Clojure, although I tend to place it where the laziness is actually required (like around the recursive call, or around the cons). You've probably noticed from the other samples posted that many Clojurians prefer to use (seq lst) instead of (not (empty? lst)), and organize their code around the not-empty case. So (if (empty? lst) empty-case not-empty-case) becomes (if (seq lst) not-empty-case empty-case) When the empty case also results in nil, you can replace the if structure with a one-armed when, because when automatically returns nil in the other case. So (if (seq lst) not-empty-case nil) becomes (when (seq lst) not-empty-case). -- 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: Remove-first function
Well obviously if you can get something to be tail-recursive you won't have the stack overflows, and the thing in your code that prevents tail recursion is having to cons the result of the recursive call. So let's try this: (defn remove-first [syb lst] (let [[before after] (loop [b [] a lst] (if (empty? lst) [b a] (if (= syb (first a)) [b (rest a)] (recur (cons (first a) b) (rest a)] (concat (reverse before) after))) user= (remove-first 4 '(1 5 3 4 2 6 674 4 2)) (1 5 3 2 6 674 4 2) I'm interested if somebody comes up with something more efficient, i.e. that doesn't require the reversal. Gary On Sat, Jul 24, 2010 at 11:41 AM, nickikt nick...@gmail.com wrote: Hallo all, I'm working trough Essentials of Programming Languages. I'm trying to right a function like this one: (defn scheme-remove-first [syb lst] (if (empty? lst) '() (if (= (first lst) syb) (rest lst) (cons (first lst) (scheme-remove-first syb (rest lst)) in a idiomatic clojure way (this is just a scheme to clojure 1:1 version). I don't like that this function produces stack overflows. I tried some stuff but I it (almost) semantically correct working but I didn't like my code. Can anyone come up with a good version? -- 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.comclojure%2bunsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- Gary Fredericks (660)-623-1095 fredericksg...@gmail.com www.gfredericks.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
Re: Remove-first function
On Sat, Jul 24, 2010 at 9:07 AM, Gary Fredericks fredericksg...@gmail.com wrote: (defn remove-first [syb lst] (let [[before after] (loop [b [] a lst] (if (empty? lst) [b a] (if (= syb (first a)) [b (rest a)] (recur (cons (first a) b) (rest a)] (concat (reverse before) after))) user= (remove-first 4 '(1 5 3 4 2 6 674 4 2)) (1 5 3 2 6 674 4 2) I'm interested if somebody comes up with something more efficient, i.e. that doesn't require the reversal. If you change (cons (first a) b) to (conj b (first a), then no reversal will be required. -- 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
Remove-first function
Hallo all, I'm working trough Essentials of Programming Languages. I'm trying to right a function like this one: (defn scheme-remove-first [syb lst] (if (empty? lst) '() (if (= (first lst) syb) (rest lst) (cons (first lst) (scheme-remove-first syb (rest lst)) in a idiomatic clojure way (this is just a scheme to clojure 1:1 version). I don't like that this function produces stack overflows. I tried some stuff but I it (almost) semantically correct working but I didn't like my code. Can anyone come up with a good version? -- 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: Remove-first function
Here's my take: (defn remove-first [x coll] (let [[pre post] (split-with #(not= x %) coll)] (concat (pre (rest post On Jul 24, 11:41 am, nickikt nick...@gmail.com wrote: Hallo all, I'm working trough Essentials of Programming Languages. I'm trying to right a function like this one: (defn scheme-remove-first [syb lst] (if (empty? lst) '() (if (= (first lst) syb) (rest lst) (cons (first lst) (scheme-remove-first syb (rest lst)) in a idiomatic clojure way (this is just a scheme to clojure 1:1 version). I don't like that this function produces stack overflows. I tried some stuff but I it (almost) semantically correct working but I didn't like my code. Can anyone come up with a good version? -- 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: Remove-first function
Hi, One way to prevent the stack overflows is to wrap it in a lazy seq. For example: (defn remove-first [x coll] (lazy-seq (when (seq coll) (let [[y ys] coll] (if (= target y) ys (cons y (remove-first x ys))) On Saturday 24 July 2010 11:41:58 nickikt wrote: Hallo all, I'm working trough Essentials of Programming Languages. I'm trying to right a function like this one: (defn scheme-remove-first [syb lst] (if (empty? lst) '() (if (= (first lst) syb) (rest lst) (cons (first lst) (scheme-remove-first syb (rest lst)) in a idiomatic clojure way (this is just a scheme to clojure 1:1 version). I don't like that this function produces stack overflows. I tried some stuff but I it (almost) semantically correct working but I didn't like my code. Can anyone come up with a good version? -- 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: Remove-first function
The simplest translation is to wrap a lazy-seq around the last line to avoid the stack overflows. On Sat, Jul 24, 2010 at 8:41 AM, nickikt nick...@gmail.com wrote: (defn scheme-remove-first [syb lst] (if (empty? lst) '() (if (= (first lst) syb) (rest lst) (cons (first lst) (scheme-remove-first syb (rest lst)) becomes (defn scheme-remove-first [syb lst] (if (empty? lst) '() (if (= (first lst) syb) (rest lst) (lazy-seq (cons (first lst) (scheme-remove-first syb (rest lst))) Also, you can omit the ' in front of the () if you like. -- 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: Remove-first function
On Sat, Jul 24, 2010 at 11:45 AM, Mark Engelberg mark.engelb...@gmail.com wrote: The simplest translation is to wrap a lazy-seq around the last line to avoid the stack overflows. Just to clarify, there are at least three reasonable places to place the call to lazy-seq. You can put lazy-seq around the full body of the function. You can place it around the cons. You can place it around the recursive call to scheme-remove-first. Each choice results in slightly different laziness behavior, i.e., when various elements are computed, but the overall semantics of the sequence remains the same and stack overflows will be avoided. Placing the lazy-seq around the recursive function call will cause scheme-remove-first to compute the first element right away, and delay the rest. Placing the lazy-seq around the full body will prevent any computation until it is asked for by a consumer. Placing the lazy-seq around the cons results in in immediate behavior for the nil and removable-item-at-front-of-list case, and delayed behavior otherwise. All are acceptable choices, but preferences vary. Probably placing lazy-seq around the full body is the most common style you'll see in Clojure, although I tend to place it where the laziness is actually required (like around the recursive call, or around the cons). You've probably noticed from the other samples posted that many Clojurians prefer to use (seq lst) instead of (not (empty? lst)), and organize their code around the not-empty case. So (if (empty? lst) empty-case not-empty-case) becomes (if (seq lst) not-empty-case empty-case) When the empty case also results in nil, you can replace the if structure with a one-armed when, because when automatically returns nil in the other case. So (if (seq lst) not-empty-case nil) becomes (when (seq lst) not-empty-case). -- 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: Remove-first function
To add one small addendum to Mark's excellent comment, if you use lazy- seq then you don't need to worry about the nil from when On Jul 24, 12:01 pm, Mark Engelberg mark.engelb...@gmail.com wrote: On Sat, Jul 24, 2010 at 11:45 AM, Mark Engelberg mark.engelb...@gmail.com wrote: The simplest translation is to wrap a lazy-seq around the last line to avoid the stack overflows. Just to clarify, there are at least three reasonable places to place the call to lazy-seq. You can put lazy-seq around the full body of the function. You can place it around the cons. You can place it around the recursive call to scheme-remove-first. Each choice results in slightly different laziness behavior, i.e., when various elements are computed, but the overall semantics of the sequence remains the same and stack overflows will be avoided. Placing the lazy-seq around the recursive function call will cause scheme-remove-first to compute the first element right away, and delay the rest. Placing the lazy-seq around the full body will prevent any computation until it is asked for by a consumer. Placing the lazy-seq around the cons results in in immediate behavior for the nil and removable-item-at-front-of-list case, and delayed behavior otherwise. All are acceptable choices, but preferences vary. Probably placing lazy-seq around the full body is the most common style you'll see in Clojure, although I tend to place it where the laziness is actually required (like around the recursive call, or around the cons). You've probably noticed from the other samples posted that many Clojurians prefer to use (seq lst) instead of (not (empty? lst)), and organize their code around the not-empty case. So (if (empty? lst) empty-case not-empty-case) becomes (if (seq lst) not-empty-case empty-case) When the empty case also results in nil, you can replace the if structure with a one-armed when, because when automatically returns nil in the other case. So (if (seq lst) not-empty-case nil) becomes (when (seq lst) not-empty-case). -- 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