Re: Comments on first function

2013-11-18 Thread Leonardo Borges
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

2013-11-17 Thread jskdlfj999
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

2010-10-26 Thread Brody Berg
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

2010-10-21 Thread Brody Berg
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

2010-10-21 Thread Michael Gardner
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 Thread Michael Gardner
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

2010-10-21 Thread songoku
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

2010-10-21 Thread Alan
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 Thread Jürgen Hötzel
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

2010-07-26 Thread Mark Engelberg
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

2010-07-25 Thread nickikt
@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

2010-07-25 Thread Gary Fredericks
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

2010-07-25 Thread Mark Engelberg
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

2010-07-24 Thread nickikt
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

2010-07-24 Thread Randy Hudson
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

2010-07-24 Thread Andrew Boekhoff
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

2010-07-24 Thread Mark Engelberg
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

2010-07-24 Thread Mark Engelberg
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

2010-07-24 Thread ataggart
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