Arc Forumnew | comments | leaders | submitlogin
Arc has no return statement?
8 points by lojic 3512 days ago | 23 comments
Is it true that Arc has no return statement? If so, how does one, for example, return a result from within an iteration before the end of the iteration?

This issue came up on the 8 Queens Problem thread ( ). I asked the question in a comment, but it's buried kind of deep.

In Ruby, one could do the following (yes, there are better ways to do this in Ruby, but it illustrates return ):

  def foo xs
    xs.each do |x|
      return x if ...
How would you do something similar in Arc?

11 points by almkglor 3512 days ago | link

For arc-wiki:

  (breakable:each x xs
   (if ...
       (break x)))
breakable is simply:

  (mac breakable (expr)
   `(point break ,expr))
point is simply:

  (mac point (name . body)
    " Creates a form which may be exited by calling `name' from within `body'. "
    (w/uniq g
      `(ccc (fn (,g)
              (let ,name [,g _]
breakable: works on any expression, not just loops and other control structures. Basically, if you need something to suddenly return a value without continuing, just add breakable: to the point you want to do so and use (break ...) to break out.

Maybe should have called it 'brittle or 'fire-extinguisher ^^


2 points by lojic 3512 days ago | link

I wonder how ccc in Arc/Scheme compares to return in Ruby with respect to efficiency. Hopefully ccc is very lightweight. It really does make me question why return wasn't defined to be part of the language.


8 points by almkglor 3512 days ago | link

Plenty efficient. Try reading the original lambda papers:

The one you need to read is "Lambda: the Ultimate GOTO"

Basically the most important realization is that the return address on the stack may be modeled as the address for a different procedure, which by a staggering coincidence just so happens to point to the code after the function call. So basically a return is itself equivalent to a function call.


7 points by sacado 3512 days ago | link

ccc is one of the strangest things in Scheme (and Arc now). Hard to get everything behind it, but it can be used to implement return statements, try-catch à la C++/Java, coroutines à la Lua, generators à la Python and of course continuation-based web apps à la Arc...

A very strange beast, and as far as I know the thing Scheme has that CL hasn't (and cannot trivially implement).


5 points by KirinDave 3512 days ago | link

It should be no surprise continuations could do all these things. Continuations are the fundamental unit of all control flow in programming.


4 points by sjs 3512 days ago | link

Arc doesn't use ccc for web apps, just good old closures.


7 points by almkglor 3512 days ago | link

Actually, the form of closure used by Arc is highly similar to a continuation passing style, so although it doesn't use 'ccc, it does use continuations.


2 points by eds 3512 days ago | link

cl-cont is a library that implements closures and runs on many CL implementations. So it's not a matter of CL can't do it, CL just has to use a library to do it.


4 points by jbert 3511 days ago | link

I think there are conceptual problems mixing unwind-protect-like constructs and call/cc.

The cl-cont lib appears to only support a subset of CL (in particular unwind-protect is not supported).

So cl-cont doesn't demonstrate that CL can support it, only that a restricted subset of CL can.

I don't know if it is possible to sensibly accommodate unwind-protect and call/cc in the same language, it seems smarter people than I have avoided doing so.


4 points by randallsquared 3511 days ago | link

Scheme's dynamic-wind serves the same purpose as unwind-protect (except with entry conditions as well, since a continuation could suddenly return into your protected code), and plays nicely with continuations. I'm not sure about the details, though.


1 point by jbert 3511 days ago | link

Thanks for that, pretty interesting. I guess that makes writing entry and exit conditions a little more interesting, since they could end up being invoked multiple times.


3 points by lojic 3512 days ago | link

That's good to here. Thanks for the links - great reference material.


1 point by treef 3511 days ago | link

i am learning how to write scheme compilers now it it looks like you just jump around your CCC's like GOTO labels - very fascinating and lower over head then functions calls (if you compile to machine level)


1 point by lojic 3512 days ago | link

Thanks. And from your comment ( ) on the 8 Queens thread, the Ruby snippet in the OP above could be implemented as:

  (def foo (xs)
    (point return
           (each x xs
                 (if (> x 3)
                     (return x)))

  (prn (foo '(1 2 3 4 5)))


2 points by almkglor 3512 days ago | link

Yes. Although breakable: is significantly more concise.

Edit: Another alternative to breakable: ... break is catch: ... throw ^^


4 points by lojic 3512 days ago | link

But breakable isn't in Arc :)


2 points by almkglor 3512 days ago | link

It's only six more nodes of code ~.~;

That said catch-throw is in ArcN, although they do have different intended usages. breakable: is supposed to be used as a modifier for existing control structures, while (catch ...) is supposed to be a control structure in its own right.


3 points by em 3509 days ago | link

Why the gensym?

(mac point (name . body) `(ccc (fn (,name) ,@body)))


1 point by almkglor 3509 days ago | link

dunno ^^. Maybe pg making a thinko ^^


2 points by sacado 3512 days ago | link

I gave a solution at . It invloves only ccc (Arc's version of call-with-current-continuation) :

  (def a (return)
    (each i xs
      (if ( ... )
        (return i)))

  arc> (ccc a)
This is a very low-level solution, if you want to put your hand into axioms. almkglor's solutions, based on point & breakable macros (from Anarki) are much cleaner, even if they just expand in the above code (or something very close).


3 points by lojic 3512 days ago | link

Just to clarify, point is in Arc and doesn't require Anarki.


1 point by gaah 3512 days ago | link

The major difference between return statements in other languages and ccc is that you can use any continuation that you can access, which means you can conditionally return to two different places in the code. As an example, here's a loop that supports "break" and "continue" (and can even break with a return value):

  (mac my-loop body
    `(ccc (fn (break)
        (while t (ccc (fn (continue) ,@body))))))
Also, I need help. I can't use my regular account because I have forgotten my password and the only password recovery thing is only accessible when you are already logged in. I am pretty sure I put my email address on my regular account, so I don't see why I can't recover it. Please post any suggestions at


1 point by Jesin 3504 days ago | link

Please note that I have my account back. I don't really know how, though. Follow the link for more info.