I had an error in configuration that caused issues with getting RPython stacklets to work properly. It took 3 days to figure out what was wrong. That won't make the working eventloop any less satisfying though. Anyway, there are several new commands such as:
If you have never read about Lever, you may want to read the last week blogpost or peek into the leverlanguage.com -website.
Before you wonder what's a continuation, lets look at a Lever code sample, as how I will introduce it just before the year changes!
# This code is in samples/ticktock.lc in its current form. main = (): print ("hello from main") schedule(tick_tock) sleep(1.0) print ("hello hello") sleep(1.0) print ("hello again") sleep(1.0) print ("and bye") tick_tock = (): i = 0 while i < 3 print("tick") sleep(0.5) print("tock") sleep(0.5) i = i + 1
This program will print:
hello from main tick tock hello hello tick tock hello again tick tock and bye
What is happening here is:
schedule(tick_tock)constructs a greenlet that calls tick_tock(), and immediately enqueues it into the event queue so it runs next time when the control is returned to the event loop.
sleep(1.0)puts the current greenlet to sleep for a second and drops the control to the event loop.
- The event loop switches to running
tick_tock(), which also sleeps after printing into the terminal.
- At this point both greenlets are sleeping, so the eventloop puts the whole thread to sleep until either of the slept greenlets have slept the intended amount.
Compatibility with callbacks
Overall the greenlets are mostly accessible from within the language, so you can mix greenlets and ordinary callbacks just fine as long as you understand what you're doing.
In Lever's terms, continuation/continulet is an extended form of a function call. This call can decide where it returns. Activating a continuation is called "switching". The mechanism forms the basis for concurrency in Lever.
Continuation is a bit like haunted mirror: Whenever a continuation is switched upon, an execution is released and the current execution takes it's place in the continuation.
Those continuations are perfect way to implement this behavior, but as a language construct the continulet doesn't tell where to return if an error occurs. Here greenlets come to be helpful: Greenlets describe where they return to, and form a sequence of returns back to the root greenlet, which is the event loop in our case.
When greenlets switch, the current greenlet takes the container for continuations from the target greenlet, sets the target greenlet as current, then switches into it. The result is that the previous execution of the previous greenlet is now suspended and the target greenlet is recovered.
Greenlets can be used to write completely untractable code. Similarly you can attach pair of chainsaws into a steel chain and get chainsaw nunchucks.
Lever submits to the idea that proper language constructs are meant to be powerful enough to be capable of harming their user when abused. They are provided in convenient forms that do not encourage wrong use, but are perfectly unable to prevent the user from being utterly stupid. This is done to encourage cleverness, as there is very thin line between the two.