Arc Forumnew | comments | leaders | submitlogin
12 points by cchooper 6130 days ago | link | parent

Aha! I think I've got it. Here's my explanation of what it's doing (I had to write all this just to work it out!)

First, the value of (catch throw) is stored in k. The catch function does this: get the current continuation and bind it locally to the symbol throw. So we get the current continuation, bind it to throw, and then return throw. So all we've done is return the current continuation at (catch throw).

In the next line, we print 1, so our output looks like this:

  => 1
In the next line, (catch (k throw)), we again get the current continuation and bind it locally to throw. But this time we call the continuation stored in k, passing throw as an argument. This rewinds us back to the beginning, so that the original (catch throw) now returns the value of throw in (catch (k throw)). This value, of course, is the current continuation at the line (catch (k throw)). This new continuation will become the new value of k.

Now you have to remember this about the continuation at (catch (k throw)): although we've rewound the stack back to the beginning and reassigned k, this continuation was created when k had the value it originally had, and it remembers this original value because of lexical scoping.

Anyway, back to the action. We've rewound back to the beginning and stored the continuation at (catch (k throw)) in k. Execution continues at (pr 1), so we get another 1 in our output.

  => 11
Now we get to (catch (k throw)) again. This time, k is the continuation originally created at (catch (k throw)), so we jump back to this line (i.e. the same line), but remember, we've gone 'back in time' (spooky music) to when k had its original value. We continue execution at (pr 2):

  => 112
and then get to the final (catch (k throw). Remember, k now has its original value in this context, so we jump right back to the start again at (catch throw) and give k yet another new value: the continuation at the second (catch (k throw)). Remember, in the context of that continuation, k is still set to its original value! (athough this isn't important because we're not going to use it.)

Now we are at the top, so (pr 1) gets executed again:

  => 1121
Then we get to (catch (k throw)). At the present time, k is bound to the continuation at the second (catch (k throw)), so we now go back in time again to when we were there. The second (catch (k throw)) returns its value (which is lost) and we get on to the next line, (pr 3)

  => 11213
Finally, we have reached the end and return nil, so the final output is:

  => 11213nil


1 point by nlavine 6129 days ago | link

Thank you very much for explaining this, but there's one thing I don't understand.

The original value of k is the continuation of (catch throw) - a procedure which takes one argument, goes back to the let, and returns its argument as the value of (catch throw). This makes sense.

The second value of k is the continuation of (catch (k throw)). As far as I can tell, this expression does not return a value to anything. Why does its continuation take an argument? Is it just throwing it away?

-----

1 point by cchooper 6129 days ago | link

Yes, the value of (catch (k throw)) is just discarded, so you could pass anything to the continuation and it wouldn't matter. The only reason it takes an argument is because all expressions in Arc have to return something, even if the value isn't used.

-----