Allow custom blocks to be shaped like C blocks ("if", "repeat", etc)
See original GitHub issue(This is a feature request. To my surprise, I couldn’t find an issue for this created yet! But maybe I missed one.)
Scratch custom blocks have always been a powerful way of simplifying code. They reduce the amount of duplicate code in a sprite by allowing you to reuse a procedure; text/number and boolean inputs complement this by letting you give specific values to the blocks in the procedure. They even allow for some neat and convenient programming tricks by way of recursion (that is, you can call a custom block from within the definition of that custom block) and “run without screen refresh” (an option that makes the custom block evaluate as quickly as possible, not allowing any other scripts to run at the same time).
Of course, Scratch custom blocks are based on the “procedures” (or “functions”) feature found in nearly all programming languages, which also feature inputs/parameters and recursion. However, procedures in many “professional” programming languages allow for a particularly unique idea absent from Scratch: creating custom control structures.
(Click me!) Blathering about text-based languages, so we can compare with Scratch :) (This section is an aside - you don't need to read it to understand the suggestion.)
Text-based programming languages are burdened by syntax, which makes creating and using custom control structures a rather daunting practice. For example, start by looking at the following JavaScript function, which prints the numbers from a given start to a given end, and see how it is called:
function printNumbers(start, end) {
for (let i = start; i <= end; i++) {
console.log(i);
}
}
printNumbers(1, 10);
This is relatively simple function and is easy for anyone who knows of for
loops (part of most introductory JS courses) to understand. Now suppose one wants to create a function which can “take behavior as an input”; that is, one where we do something else with the number instead of console.log
-ing it, and what we do is specified by the code calling printNumbers
instead of inside printNumbers
itself. The actual code defining it isn’t really complicated, but the way we have to call printNumbers
afterwords is sort of icky:
function useNumbers(start, end, func) {
for (let i = start; i <= end; i++) {
func(i);
}
}
useNumbers(1, 10, function(number) {
console.log(number * 2);
});
Take particular note that even though for
and useNumbers
are fundamentally similar in that they are both control structures, the built-in for
loop uses “ordinary JS” syntax that most are familiar with, whereas the user-defined useNumbers
function requires passing a first-class function. Treating a function as a value is already something new JavaScript programmers are unfamiliar with; passing one into a function and then calling it from inside that function is only more confusing. In Scratch design lingo, this is a “high ceiling, high floor” feature: while custom control structures are a powerful idea, they are difficult to get started with.
However, this brings us to custom control structures in Scratch…
Scratch is built around being “high ceiling, low floor”, meaning powerful but easy to get started with. And while custom control structures in other programming languages are typically a high-floor feature, Scratch has the advantage of being block-based, so syntax is essentially not an issue. For example, let’s look at a simple “show numbers from A to B” custom block:
Now suppose we want to make a custom block which lets the user decide what gets done with the number, instead of just “say”-ing it. This is conceptual syntax, but I’ll use it to demonstrate:
Indeed, writing this was as simple as replacing the “say (Number) for 1 secs” with a block-shaped input.
But how would this look in the block palette (where custom blocks show up)? Well, perhaps it’s not actually surprising:
Making use of it would be just as simple; you’d simply use the “Number” variable inside the script:
Update December 14: Be sure to take a look at this additional section proposing custom block “outputs”, as well as the immediately-below comment with interesting examples of custom C-blocks!
PS, regarding implementation, this would be pretty easy to fit into the UI – just add another option below “run without screen refresh”, something along the lines of “C-shaped”. (Probably a better string than that, since it’s not particularly self-descriptive to someone who doesn’t already know the term. But “run without screen refresh” really isn’t that much better - perhaps both ought to have more details that show up by hovering over an adjacent “info” bubble!)
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:10 (9 by maintainers)
Top GitHub Comments
It’d be awesome if extensions could extend the custom block interface, so callbacks and custom reporters could be opted into by advanced users without adding potentially confusing new features for everyone else, and so (depending on the extension approval/import process or whatever) power-users could just write the extension to add these kinds of advanced features as they need them
@joker314 I did think about E-shape blocks (etc) while writing this suggestion, but I decided not to include them because they “raise the floor” a lot (so, high-floor instead of low-floor).
PS, neat sketchup. I was thinking of a different syntax though. I don’t think your screenshot is very intuitive; instead, I suggest something like this:
As you can see, the “while” block is an actual C-shape, which is how it will display in the block palette. This matches how the “placeholder block” in current custom blocks match how the block will actually display in the block palette.