Support named loops with new recur-to form? (with cljs proof of concept)

395 views
Skip to first unread message

Michał Marczyk

unread,
Jul 9, 2013, 4:48:34 PM7/9/13
to cloju...@googlegroups.com
Hi,

One thing which I have found inconvenient about loop/recur on multiple
occasions is that it only allows the innermost loop as the target (and
the enclosing fn only if not in a loop form). It's come up on the main
mailing list just now:

https://groups.google.com/d/msg/clojure/-oPnklPSLx8/j4Euim4XCycJ

prompting me finally to implement the idea I had about this. So, I'm
wondering if something like this would be considered desirable in
Clojure?

The syntax I have in mind is (loop loop-name [...] ...) / (recur-to
loop-name ...), where loop-name is optional in the loop and plain
recur can always be used to recur to the innermost loop, regardless of
whether it is named or not.

Here's an example in ClojureScript:

(let [arr (make-array 10)]
(dotimes [i 10]
(aset arr i (make-array 10)))
(loop outer [i 0]
(if (< i 10)
(loop inner [j 0]
(if (< j 10)
(do (aset arr i j :foo)
(recur (inc j)))
(recur-to outer (inc i)))) arr)))
;; returns a 10x10 2D array filled with :foos

I have implemented a proof of concept in ClojureScript. For now, it
only handles recur-to for named loops; presumably recur-to with named
fns should be possible as well. It's available here if you'd like to
give it a try:

https://github.com/michalmarczyk/clojurescript/tree/recur-to

The actual commit:

https://github.com/michalmarczyk/clojurescript/commit/feba0a078138da08d584a67e671415fc403fa093

The implementation takes advantage of JavaScript's support for
labelling loops. (Of course Java allows that too.)

Cheers,
Michał

Timothy Baldridge

unread,
Jul 9, 2013, 4:50:04 PM7/9/13
to cloju...@googlegroups.com
In other words...you want goto?



--
You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure-dev...@googlegroups.com.
To post to this group, send email to cloju...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojure-dev.
For more options, visit https://groups.google.com/groups/opt_out.





--
“One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.”
(Robert Firth)

Michał Marczyk

unread,
Jul 9, 2013, 5:00:11 PM7/9/13
to cloju...@googlegroups.com
On 9 July 2013 22:50, Timothy Baldridge <tbald...@gmail.com> wrote:
> In other words...you want goto?

Well, I don't think that follows in any way at all.

Convenient control over multi-level loops is available in any language
which handles looping through function calls + TCE (in particular,
(let outer (...) (let inner (...) ...)) is not at all unusual in
Scheme -- this is where I'm getting the syntax from). If at any point
Clojure gets TCE (presumably because the JVM does), we'll have this
anyway. In any case, goto within a function can be emulated with plain
loops + case, for example, no need for control over enclosing loops.

Note that recur-to still needs to be in the tail position, it's just
that it allows you to jump directly to the enclosing loop, rather
than, say, returning a vector and using destructuring (at a perf cost)
if there is more than one outer loop local which needs to change for
the next iteration.

Cheers,
Michał

Michał Marczyk

unread,
Jul 9, 2013, 5:36:10 PM7/9/13
to cloju...@googlegroups.com
On 9 July 2013 23:00, Michał Marczyk <michal....@gmail.com> wrote:
> Note that recur-to still needs to be in the tail position, [...]

Just to be very clear on this, since it's a key point:

For recur-to to work, it must be in the tail position of the inner
loop, which in turn must be in the tail position of the enclosing
loop, which in turn must be in the tail position of its enclosing
loop, all the way up to the target named loop.

The PCO impl does enforce that:

(loop asdf [x false]
(loop [y :foo]
(recur-to asdf true))
(prn :bar))
;; analysis-error

Cheers,
Michał

Mark Engelberg

unread,
Jul 9, 2013, 6:25:54 PM7/9/13
to cloju...@googlegroups.com
I have definitely wanted this in the past.

Softaddicts

unread,
Jul 9, 2013, 6:36:20 PM7/9/13
to cloju...@googlegroups.com
Yeah ! ... half-joking ;)

Luc P.
Softaddicts<lprefo...@softaddicts.ca> sent by ibisMail from my ipad!

Mark Engelberg

unread,
Jul 9, 2013, 6:44:45 PM7/9/13
to cloju...@googlegroups.com
To clarify, when translating code that roughly corresponded to a nested series of for loops with a mixture of break and continue, it was extremely ugly to convert to loop-recur without the ability to recur directly to an outer loop.

David Nolen

unread,
Jul 24, 2013, 3:52:43 PM7/24/13
to cloju...@googlegroups.com
Having written some convoluted inner loops in CLJ and CLJS this would be a most welcome feature.

David

Alex Miller

unread,
Jul 24, 2013, 4:51:40 PM7/24/13
to cloju...@googlegroups.com
Can someone make a design page on the wiki?  

I think a child page of Core would be a good place. http://dev.clojure.org/display/design/Core

Michał Marczyk

unread,
Jul 25, 2013, 11:40:55 AM7/25/13
to cloju...@googlegroups.com
On 24 July 2013 22:51, Alex Miller <al...@puredanger.com> wrote:
> Can someone make a design page on the wiki?
>
> I think a child page of Core would be a good place.
> http://dev.clojure.org/display/design/Core

Sure, I'll write up a proposal.

Cheers,
M.

Michał Marczyk

unread,
Jul 25, 2013, 12:09:52 PM7/25/13
to cloju...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages