Scheme style blocks in Snap!

in the unix command line, you can use | to transfer the output of a command to another command. for example, you could run a program that outputs Hello, World! into the terminal. you could run the command like this: ./helloworld. now, i want to transfer the output of ./helloworld to another program, for example, grep, which is a program that searches for a certain string in the output you pipe to it. you would do that by typing ./helloworld | grep hello. maybe a screenshot will help:

as you can see here, i first ran the cowsay command, that prints an ASCII representation of a cow to the console saying the specified text. next, i ran it again, but this time, i piped the output to grep and told grep to search cowsay's output for hello. you can use other programs other than grep for different tasks, but I'm using it here as an example

I saw @joecooldoo's reply but want to go a level lower in abstraction. In Unix-family systems, whenever a process starts up it is given three initial ports (an abstraction to which you can send, and from which you can read, data) called stdin (standard input), stdout (standard output), and stderr (standard error). The vast majority of programs have one input data stream and one output stream; they are typically programmed to read from stdin and write to stdout. (We'll get to stderr later.)

The most common case is that a command line just runs one program. In that case, one process is started; its stdin is connected to the keyboard and its stdout and stderr are connected to the screen. (In both cases, there's a lot of software between the process and the actual hardware.)

But if you give a command of the form A | B (where A and B are things you could have typed as a standalone command), the process for A has its stdout hooked up to the stdin of the process for B. There is buffering in the connection for efficiency, so you don't have to switch processes for each character output by A.

That's how it works! Note that A's stderr, which is meant to be used for error messages, is not redirected to B's stdin; it still goes to the screen. (There are other syntax elements you can use to redirect stderr if you actually want to, but usually you want the user to see error messages.) This is why stderr exists.

By the way, I hesitantly lay claim to prior work on this idea. I was at a startup, although that word hadn't been invented yet, called Composition Technology, that did computer typesetting of mathematics, before there was $$\TeX$$. My boss, Lowell Hawkinson, implemented an interprocess port abstraction, and I used it to implement a pipe-like command line notation, around 1971. Wikipedia says Unix development started in 1969 and the first public release was in 1973. This range of dates is what makes me hesitant: I don't know if Lowell had some inside scoop from Bell Labs before then, but I sure didn't. I learned about Unix when I got to LSRHS in 1979.

pic
Welp, I'm not sure what this means. G_last is defined in the global environment.

Hmm. Could you post a link again? I can't find it in all these posts! Tnx.

Sure: Snap! Build Your Own Blocks

Just as I suspected, it's due to metaprogramming. When you create a script using metaprogramming, it strips away any context variables in it had, which throws an error when you try to run it.


So you have to run the script in a sprite's context using tell or ask

All you have to do is to change call to ask, and it'll work perfectly.


Do I agree with this behavior? No, as I think the script in the call block should be able to at least access global variables no matter if the context is set or not.

A continuation of my previous problem:

pic

Currying doesn't work b/c it doesn't have the context of the outer λ. Is there anything I can do to fix this?

You may "rebind" the prepared lambda with
untitled script pic - 2024-04-07T023225.186

Yes, you can use
untitled script pic (3)

Can you give me an example?

Replace the (...) block with the script you need to call.

So, like

pic

Or

?

I've tried both, and they didn't work.

Replace the ask block with the call ([] of []) block. Like this

P.S. I didn't realize the of block could rebind scripts to other scripts, so that's a much much better method than using tell or ask.

Unfortunately, it still doesn't work.
pic

Check whether that G123 exists in the image in the input names. Cannot find G123 in input names. Is that what you mean?

I'm trying to get Currying working. G123 should be passed in from the outer λ.

Aargh. This is really annoying. While I'm trying to convince Jens that the global environment should always be available no matter what, let's try this:

and then translate


(where D is free in this lambda) to

where G187 is the gensym corresponding to the relevant binding of D. (You have to maintain a translation dictionary with the lexically current binding of formal parameters to gensyms, unless the translation of D to G187 has already happened before you get to this stage.)

So no variables are used at all except for the one in gensym-holder and the locally-bound ones in the IGNORE statements. And so it doesn't matter what unpleasant rules Snap! has about procedures made from trees.

It's intended as a reply to Brian, but the forum does not allow to correct this ...

The call-site binding of the block variables works in a subtly different way
untitled script pic - 2024-04-07T214928.356

Your example can be recreated as
blocks variable script pic (3)

It's just as well that it's directed to @bluebaritone21; that's who's writing the actual code! ;~)

I'm still trying to figure out why block variables are enough for this.