Today's vocabulary word
In the script
we say that the continuation of the block
is the script
The continuation means "what is left to do once we compute this result?" Similarly, the continuation of the block
is the script
Note that the continuation of a reporter block is a script with one input, whereas the continuation of a command block is a script with no inputs.
Today's new Snap! feature
CALL / RUN ___ WITH CURRENT CONTINUATION calls or runs its input (which must be a script with one input) with the CALL / RUN...CONTINUATION block's continuation as its input value. Here's how you'd use it (if only we had lists):
Offline
Interesting! Will this be a daily post?
Offline
shadow_7283 wrote:
Interesting! Will this be a daily post?
Naw, we're not putting new features in Snap!, at least not until we get the old ones (such as lists) working.
This one is sort of a joke, having to do with the fact that I'm visiting Boston next week. You know how every time we visit the S.T., they complain that BYOB is too complicated for kids to understand. Well, in Scheme there are (exactly) two features that really are too complicated for just about anyone to understand: hygienic macros (look it up) and call-with-current-continuation. So I'm hoping that when I next see Mitchel I can make his head explode. He won't even have to see a demo; just seeing a block with that name should do it.
If we really want this as a Snap! feature, it needs a more careful design, to work out how much besides the continuation we might need to encapsulate. For example, suppose some piece of code expects a certain sprite to be hidden, and you make a continuation into it, and later you call the continuation with that sprite shown. Should we hide the sprite? And similarly remember the state of all the other sprites? Call⁄cc works well in Scheme because there's not that much state in a Scheme program; you do everything functionally.
My original idea was just to post "hey, there's a new block in tonight's build" and watch you guys's heads explode too, but the Wikipedia article on call⁄cc is really pretty opaque, so I decided a little bit of explanation was needed.
Call⁄cc can be used for nonlocal exit, as in the MULT example I posted, and also for a scheduler with multiple threads (each represented as a continuation), and also for error handling -- basically any control structure you can imagine can be made with it. When they invented it for Scheme, it replaced half a dozen or so special-purpose control mechanisms.
The interesting thing is that it's pretty trivial to implement, just a couple of lines in the Javascript code, because the Snap! interpreter already has the continuation of a computation in a variable; that's how it knows where to return when a block finishes running. So it was just a question of wrapping a lambda around it.
But understanding how to use it is tricky. Note, for instance, in the MULT picture, that because I used the reporter form of call⁄cc, BREAK is a reporter, but I call it using RUN, not CALL, because the place where I want to call it is a jigsaw-shaped slot. And that doesn't matter, because when you call or run a continuation, it never returns! Or rather, it returns someplace else, namely to whoever called call⁄cc to create it.
Jens spent the early part of yesterday saying "maybe later" but once I explained it to him he instantly fell in love with it.
Offline
call/cc
okay, I'm still unsure about a lot of things regarding call/cc, despite being glad that it works. I've been spending the better part of today experimenting with putting the current continuation into an upvar (some of you might have seen a version of this online) and convincing Brian that upvars are just what we need here, so you guys can get it yourselves. But then when Brian finally (gave in) agreed and we came up with a design we both found cool and I got it work I suddenly didn't like it anymore myself, haha! So now, for the moment, I'm back to the most minimalistic block labelling imaginable, call/cc, for both version of the block (command and reporter). As Brian pointed out to me this will be the easiest form for you to look up examples on the internet and in text books, and that really convinces me.
Offline
I thought I understood, but when trying to use it in Snap!, I had little success.
Offline
Jens wrote:
But then when Brian finally (gave in) agreed and we came up with a design we both found cool and I got it work I suddenly didn't like it anymore myself, haha!
I hate when this happens! This isn't the first time that each of us has convinced the other about something, and then we really don't know what to do.
For the record, here's what Jens's upvar version looks like (mocked up in BYOB):
So for example if you do this:
you are saving the continuation in variable FOO and reporting 5 from the with/do block, so Alonzo says 7 and moves 10 steps. Then if, later, you do
you are saying to report 30 from the with/do block, and so Alonzo says 32 and moves 10 steps.
This upvar notation is the BYOBified version of something that's also in the literature under the name "let/cc" -- an alternative version of call⁄cc as a special form, to avoid the confusing fact that there are three different procedures involved with call⁄cc: (1) call⁄cc itself, (2) its input, and (3) the continuation that it creates. Let/cc is a special form, and instead of a procedure as input it just takes a body (a script, in BYOB), so the only procedure you have to think about is the continuation itself.
@shadow and 14God: The easiest application of continuations to understand is probably nonlocal exit. In those other languages you can say things like
forever { ... if (something) break; ... }
where "break" means "get me out of the innermost loop." To do this with let/cc you'd say
In this simple case, you wouldn't even need the BREAK variable; you could just drag CURRENT CONTINUATION into the RUN block. But this technique even allows something those other languages can't do, which is nested loops with a separate break command (with a different name) for each loop, so you can exit from as many as you want.
Here's the run/cc equivalent. It isn't really very different, except that it needs an explicit lambda:
PS Oops I messed up; "continuation" and "current continuation" in the last picture are supposed to be the same -- it doesn't matter which name you use.
Last edited by bharvey (2011-10-11 11:33:35)
Offline
so... does anybody here actually grok call/cc in Snap? (I sure didn't until Brian personally and patiently tutored me). What's your opinion about our upvar argument, which version do you find helps you better understand this, the plain one or one with upvars?
Offline
bharvey wrote:
Jens wrote:
But then when Brian finally (gave in) agreed and we came up with a design we both found cool and I got it work I suddenly didn't like it anymore myself, haha!
I hate when this happens! This isn't the first time that each of us has convinced the other about something, and then we really don't know what to do.
For the record, here's what Jens's upvar version looks like (mocked up in BYOB):
http://byob.berkeley.edu/letcc.png
So for example if you do this:
http://byob.berkeley.edu/letex1.png
you are saving the continuation in variable FOO and reporting 5 from the with/do block, so Alonzo says 7 and moves 10 steps. Then if, later, you do
http://byob.berkeley.edu/letex2.png
you are saying to report 30 from the with/do block, and so Alonzo says 32 and moves 10 steps.
This upvar notation is the BYOBified version of something that's also in the literature under the name "let/cc" -- an alternative version of call⁄cc as a special form, to avoid the confusing fact that there are three different procedures involved with call⁄cc: (1) call⁄cc itself, (2) its input, and (3) the continuation that it creates. Let/cc is a special form, and instead of a procedure as input it just takes a body (a script, in BYOB), so the only procedure you have to think about is the continuation itself.
@shadow and 14God: The easiest application of continuations to understand is probably nonlocal exit. In those other languages you can say things likeCode:
forever { ... if (something) break; ... }where "break" means "get me out of the innermost loop." To do this with let/cc you'd say
http://byob.berkeley.edu/breakex.png
In this simple case, you wouldn't even need the BREAK variable; you could just drag CURRENT CONTINUATION into the RUN block. But this technique even allows something those other languages can't do, which is nested loops with a separate break command (with a different name) for each loop, so you can exit from as many as you want.
Here's the run/cc equivalent. It isn't really very different, except that it needs an explicit lambda:
http://byob.berkeley.edu/runccex.png
PS Oops I messed up; "continuation" and "current continuation" in the last picture are supposed to be the same -- it doesn't matter which name you use.
Ah! Loop-breaking!
I was wondering if the sprite-background interface can handle all the new features in Snap!, or, rather, that Snap! is too advanced to the sprite-background interface. For a simple example, imagine JS Canvas programming with the sprite interface—now you suddenly are restricted to pre-made images, and simple line drawing. Ew!
An interface I might suggest would be the Interface Builder (Mac apps) interface. Basically, you can drag in objects like a loading bar, and link it to a variable (called an IBOutlet). Objects have their own methods and properties. So, I can drag a loading bar on to my app's screen, link it up to a variable called Loading_Bar, then run a block that could look like this:
(The original Objective-C code would be [Loading_Bar startAnimation];)
Here's an Interface Builder screenshot where I'm hooking up a button with the text Close Window to the method Close Window of the Window.
http://www.imgpaste.com/jKfg.png (too wide to display, sorry!)
Last edited by Hardmath123 (2011-10-12 10:21:17)
Offline
Hi Hardmath123,
you can already do this kind of GUI-Building with Morphic.js:
http://www.scratch.mit.edu/ext/youtube/?v=QUDNpl0YJqA
which we're creating Snap on top of. But we're probably not going to include "widgets" in Snap, instead we prefer that you create your own ones using our sprite-nesting feature and prototypal inheritance.
Last edited by Jens (2011-10-12 10:21:30)
Offline
Jens wrote:
Hi Hardmath123,
you can already do this kind of GUI-Building with Morphic.js:
http://www.scratch.mit.edu/ext/youtube/?v=QUDNpl0YJqA
which we're creating Snap on top of. But we're probably not going to include "widgets" in Snap, instead we prefer that you create your own ones using our sprite-nesting feature and prototypal inheritance.
Yeah, I realize it's beside the point to do stuff for the programmer, as this would be an educational tool (I hope), but I think sprites are a bit too simple for how high BYOB/Snap! programming can be.
Offline
Maybe you can have a sort of CGSprite make method, which allows you to spontaneously create a totally blank sprite, which can be customized in terms of appearance and position.
Mockup screenshot coming up, 'cause I'm terrible at verbal explanations.
Offline
Hardmath123 wrote:
(...) but I think sprites are a bit too simple for how high BYOB/Snap! programming can be.
Ah, thanks for the compliment. See, we're going to have first-class costumes at some point (4.1). Then you'll be able to change every pixel in any costume programmatically and even create new and additional ones using blocks, which really should take care of what you're suggesting.
Offline
Ah. Well that was what I was aiming at. But here's the mockup, anyway:
(New CGSprite) acts like (clone) but extensible.
Last edited by Hardmath123 (2011-10-12 10:58:26)
Offline
@Jens & bharvey
"What's your opinion about our upvar argument, which version do you find helps you better understand this, the plain one or one with upvars?"
Sorry it's exactly like you were talking chinese to me. But no problem I shall try to follow you in any circumstance. By the way Brian is such a nice and patient teacher that all this will come clear for me in due time (not to long because I have just turned my 70 yrs !)
Offline
Thank you movie comparison!
Offline
MathWizz wrote:
I found a bug. THE BLOCK reports itself when it contains nothing.
What would you like it to report? We actually talked about this case and didn't have a really good answer. For THE SCRIPT it makes sense to have a zero-length script that does nothing, but not for a reporter block. We could red-border it; would that be better?
Offline
After I posted that I did second guess myself thinking that you more than likely already knew about this but I didn't change it because I was to lazy.
Anyway... Redborder, maybe... I don't know if this is the direction you want to go in, but you could make another primitive NIL and have it report that.
Offline
MathWizz wrote:
I found a bug. THE BLOCK reports itself when it contains nothing.
That is ment to happen.
Offline