Script builder library (Part 1)


how do you mispell cor as cor and not notice it?

oh i see now

Well here's what I came up with:

But for some reason it isn't working. I suspect that this might be because the (() to () from {}) block and the ({} put after {}) block modifies the original. I don't know how to fix this because I don't know how to make a copy of a block.



I don't understand. You can already put code in a variable without the use of a library. Blocks are first-class.

Hold on, I realized I made a mistake in the previous definition I gave. Here is the updated version:

Also, now I made it so the ({} put after {}), (() to () from {}), e.t.c. do not modify the given scripts/expressions and instead return a new one. So now this works. You are going to have to re-download the library.

should be misspell and

should be Brian.

I've been trying to make macros work, but it's kind of hard since I can't put a continuation as a block argument.

You're digging around the JS code. Can't you just use CALL W/CONTINUATION?

Yes, I did, and to prevent the actual continuation from running afterwards I put a stop this script block. But when you do that in a loop it will stop the entire loop and won't let the loop finish. There's no continue block and I don't want to always have to put a continue-able loop for it to work.

Also I was thinking to make inputs for the macros

Yeah, in the end we'll have to make macro generation part of the make-a-block dialog, with a checkbox or something for a macro. It's going to require some careful design, because, among other issues, there will be command macros, which are syntactically commands, so they click into a stack, but they report a value. So maybe you shouldn't try too hard.

Oh, wait, you said stop this script? Not stop this block? Try that.

What do You consider the crucial elements of a macro?
Runtime binding/access to variables?
With "create variables" library a kind of a macro can be built.
Variables can be manipulated with
SimpleMacro script pic (1)

and used with #inline
SimpleMacro script pic

"Macro" can use the already declared var or create a new one.
SimpleMacro script pic (4)

Example project:

Oh... For Logo macros, what turned out to be crucial was the ability to run a STOP THIS BLOCK (just called "stop" in Logo) or a REPORT in the context of the caller of the macro. That was the only thing that couldn't be done any other way; variables weren't so problematic because Logo is dynamically scoped.

But also, one of the points of macros is to put the cognitive burden on the macro writer rather than the macro user. So your solution, although brilliant, exposes too much mechanism. But I now wonder if it would be possible to add a fourth choice "caller's" to the global/sprite/script pulldown, which would be the same as script but in the environment found by descending one step in the stack of contexts. I'm not actually sure that would be useful; I have to write some actual code.

Ideally, the cognitive burden on the macro writer could be reduced too, if we let the MACRO block itself hide some mechanism. For example, imagine a prepass over the macro's script that turns every variable reference that isn't to the macro's own variables into one of your #inline things.

Some of the classic Logo examples can be done differently in Snap!. For example,

.macro localmake :var :val
output (list "local (word "" :var) "make (word "" :var) :val)

So the call

localmake "foo 87


local "foo make "foo 87

We have, in libraries, a LET block that uses an upvar for the same purpose, creating a script variable in the caller and giving it a value.

Here's the tutorial on Logo macros:

We have the slight complication that we want to support both command macros and reporter macros (including predicates).

Macros aside, though, I also want to be able to define custom blocks programmatically:
preloaded libraries script pic
(never mind the handwave of where that orange LIST block came from) so that I can use it this way:

I didn't have to use sentence->list; I just couldn't be bothered pulling out five input slots in the LIST block.

As you can see, my ideas about the notation are iffy, but you can still see what I want to be able to do.

SimpleMacro script pic (7)
already stops the toplevel script.


SimpleMacro script pic (8)
acts exactly this way.
Those two scripts gave the same result
SimpleMacro script pic (9)
SimpleMacro script pic (11)
So variables created this way acts exactly as expected for script scoped


Macros are usually defined out of the context of the target scripts. So how external variables can be referenced or dragged into slots?
Isn't the clear distinction between local and external variables a virtue rather than a drawback?
Or maybe a declarative import (just idea without implementation)
SimpleMacro script pic (12)

More to come...

I did an update. now I removed the blocks looking at individual blocks from scripts, and replaced them with the "blocks in" block, which reports a list of all the individual blocks. I did this because

So why not just make it report a list instead? It also decreases the number of blocks in the library.

Though, I didn't provide a block to get all the nested blocks in the blocks as a replacement for the "# of blocks in" block (not to be confused with the former "length of" block), but you can write a block that does that anyway without the use of JavaScript. (In theory, I hadn't actually made the block). I made this easier by providing the "# of slots in" block.

Also I was thinking of doing the same for the inputs, where it would report a list of all the inputs, and you would be able to change each input from the list (because it stores references to them). But then I realized doing this would probably make changing text inputs impossible, since probably I can't make it store a reference to the text, only a copy of it.

I also made it so the blocks modify the actual block and no longer report a modified copy of the block. Because this is obviously going to be a problem I provided a "copy" block which copies a script.

Do you guys think these changes were a good idea? If this was a terrible idea, then fortunately I have a copy of the blocks prior to this change on my computer. Hopefully I don't get ransomware.

I don't now much about the underlying code, but this looks great! It really feels really 'Snap-y', like the list/HOF blocks, where there are only a few blocks, but they can be combined in different ways to do anything you want. I agree that it would be nice to have these blocks use the list blocks, but I think that there are just too many new blocks added to make that possible.

I also noticed that as of yet, it appears you cannot use these with the HOF blocks, so script builder script pic
doesn't actually work. (Unless I am missing something, which is more than likely).

This also brings up the design problem that unless you use variables, blocks with scripts in them tend to get big quite fast, with lots of white (or in this case orange) space. Maybe scripts (ant other large inputs) should default to a new line, so that the script would look more like this:
script builder script pic (1)

I think that the although second image looks much better, the first image is more readable, as all the text lines up in the center, so you can read it like a single sentence, whereas the second blocks reads more like a paragraph, and the eye has to scan across multiple lines.

Another idea, which I think could be applicable to more than just scripts, is the ability to drag an output onto the scripting area, and have it show up as a regular block, like this:
This could be extended to outputs from list blocks as well. Although you can just set a variable to the output, when developing a script, it would be much easier to both see the output, and interact with it immediately.

These last two suggestions are more general questions about the implementation that need to be answered, than suggestions for your library in particular.

Keep up the great work!

To get the block in the scripting area, run this script:

The block in the sprite speech bubble will be tangible. Just drag it into the scripting area normally.

That's awesome. I can think of many great thing you could with this.