On 8/19/2017 6:16 AM, Zelphir Kaltstahl wrote:
I looked at the code for a while again and think I now begin to understand it a
bit more:
I did not know `(let/ec` so I had to read about it. It says, that it is equivalent to
`(call/ec proc` or something, which is equivalent to `(call-with-escape-continuation
...`. Uff … I don't know much about continuations, except from a vague idea of when they
are called. The idea gets mingled with structures in other programming languages which
are "catching exceptions" and such stuff. I don't know this stuff, so I guess
`(call-with-escape-continuation` works like catching an exception, which is not really an
exception, but just a signal, that code is returning. Then instead of simply returning,
the escape continuation is called. This is done implicitly without specifying a named
exception for returning and without defining some conditional structure on the side where
it would return to.
This could all be wrong ...
It's at least a misconception. Continuations are _not_ exceptions -
they are a much lower level construct. Exception handling is built on
top of continuations.
There is nothing magic or mysterious about a continuation. In Scheme,
continuations are the moral equivalent of GOTO with arguments [yes, you
can pass arguments to continuations]. In actual fact they can be used
to write code that jumps around arbitrarily ... but the standard uses
are more structured.
When you say, (let/ec foo ... ) , all that's happening is the compiler
defines a pseudo-function named 'foo' that when called will exit from
the block of code in the scope of the let. (call/cc foo ...) does the
same, but assumes you will be immediately calling a function instead of
executing inline code. Invoking foo anywhere in the function (or its
descendants) will jump back out of the call chain. Scheme makes
invoking the continuation look like a function call even though it
really is a jump that won't return.
You do need to learn about continuations because they are the underlying
basis of many programming techniques: exceptions, co-routines, threads,
etc. ... all of which can be implemented directly in Scheme without
dipping into assembler.
Dan Friedman's paper is great, but is too technical and too
Scheme-centric for beginners. The Wikipedia article on continuations
(https://en.wikipedia.org/wiki/Continuation) is simpler to understand.
Be sure to look through the "further reading" and links at the end. But
the way to really get a handle on what continuations are is to read a
book on compilers - at which point you'll realize that they really are
little more than a branch target.
However, with this kind of idea about escape continuations in mind, I think I get the idea behind
using `(let/ec` in the code. When a place wants to exit, it is stopped from doing so, giving it
more work, as if to say: "Hey wait! You can escape, but only if you do THIS! (escape
continuation)" Then the place, desperately wanting to escape thinks: "Damn, OK, I'll do
just that little bit of code more.", not realizing, that it is stuck in a loop. How mean.
I wonder however, if there is no simpler way of doing this.
I mean, if `(place-channel-get ...)` blocks, could I simply put stuff into an
endless loop without escape continuation and only break the loop, if a certain
symbol is received on the channel?
How are you going to "break out" of the loop? In Scheme there are only
3 ways to jump over or out of a block of code: return from a function,
invoke a continuation, or raise an exception. The loop I wrote was in
the middle of the function where returning was not an option and there
was no reason to raise an exception. Delimited (aka "escape")
continuations are a structured way to jump out of a loop.
A 'do' loop is a macro that hides continuations inside. You might as
well learn to use them directly.
Since `(place-channel-get ...)` is blocking, it should not generate any CPU
load, when there is no message on the channel (right?).
Why do I need to introduce something as complex as `(let/ec ...)`?
Because you need to exit from of the - otherwise infinite - loop.
I appreciate the code shared here. I just hesitate to use it, when I don't even
understand it myself or when I am super unsure about understanding it (escape
continuations). I am also thinking about how I can replace all the exclamation
mark procedures, before adding it to my other code, which does not deal with
assignments so far.
Don't get too hung up on style points ... the goal is to write code that
is easy to read and that you [and others] will understand without
needing days of intensive study. If avoiding assignments makes your
code longer and more convoluted, then doing it was a bad thing.
Is there some easy to understand introduction to continuations in Racket? (not
a super clever and scientific Friedman paper, which I'd probably need 1 year to
actually understand :D)
A book on compiler construction is your best bet.
Scheme - and thus Racket which is based on it - exposes continuations
in ways that most other language don't. You will need to learn the ways
that Scheme defines and invoke continuations to use them effectively ...
but there's really no magic going on.
George
--
You received this message because you are subscribed to the Google Groups "Racket
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.