(And for context, here is Christophe's 'while-let' from 2009):
(defmacro while-let
"Makes it easy to continue processing an expression as long as it is true"
[binding & forms]
`(loop []
(when-let ~binding
~@forms
(recur))))
On Wed, Mar 5, 2014 at 5:09 AM, Dan Cross <[email protected]> wrote:
> On Saturday, October 17, 2009 11:42:28 PM UTC-4, mbrodersen wrote:
>
>> It would be great to have while-let in contrib. Then I don't have to
>> maintain let-while myself :-)
>
>
> I'm reviving this ancient thread because of core.async. This seems like
> just the thing for the common pattern of looping over data received from a
> channel until the channel is closed.
>
> Consider the following snippet of Go code that illustrates a common idiom:
>
> func printints(c chan int) {
> for v := range c {
> fmt.Println(v)
> }
> fmt.Println("Channel closed!")
> }
>
> (Note: often this would be called in a go routine by e.g., a closure that
> adds and removes from a wait group or something similar, but I omit that
> here for brevity.)
>
> In particular, notice how the 'range' operator interacts with both the
> channel and the 'for' construct to loop over the values received on the
> channel until the channel is closed. I'd like to do something similar in
> Clojure, but I don't believe that we have an exact analogue; the closest
> I've been able to come up with are the two:
>
> (loop []
> (when-let [v (<! c)]
> (println v)
> (recur)))
>
> and
>
> (while
> (when-let [d (<! c)]
> (println d)
> d))
>
> These work, but neither strikes me as particularly elegant (in particular,
> the use of 'while' here is ugly). Speaking of 'while, I also see this in
> some places such as the
>
> (while true (let [v (!< c)] (...)))
>
> However, that won't exit when the channel closes. Indeed, the loop will
> just set 'v' to 'nil' forever after the channel closes (or at least as long
> as 'true' is 'true').
>
> What I really want is a loop that iterates (or recurses) while something
> is true, like the 'while-let' that was discussed in this thread. That
> seems to capture the semantics of exactly what I want to do when looping
> over the items placed onto a channel. In particular:
>
> - It captures the semantics of doing something *while* a binding is true;
> exactly what we want when binding something from a channel get operation.
> - It encapsulates the side-effect in the binding form.
> - It's simpler and more elegant than the alternatives.
>
> Indeed, the 'loop' above is really the body of the 'while-let' macro that
> Christophe Grand posted back in 2009.
>
> Unfortunately, it doesn't seem to have made it into one of the core
> libraries. Did it ever make it into contrib? I don't see it in the "Where
> Did Clojure.Contrib Go" list. The only references to it that I see are to
> an apparent reimplementation:
>
> https://www.versioneye.com/clojure/while-let:while-let/0.1.0 (which
> ultimately leads to...)
> https://github.com/markmandel/while-let/blob/master/src/while_let/core.clj
>
> I don't like that nearly as much as Christophe's version, but it is worth
> noting that the author specifically mentions core.async as well, thus
> implying that there is wider demand for this sort of thing. Is it worth
> asking that this be added to e.g. the core library? Or even to core.async?
>
> Thanks,
>
> - Dan C.
>
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.