Suggested process for handling variable number of parameters for a custom block

FYI This is about variable options, not my costume reporter - it's just an example

So I wrote a reporter to generate text using a fixed matrix type font

And then I decided to add ability to colour the background

And then I thought it might be nice to have a border option

And what about changing colour of text directly rather than using the pen colour

But then I've ended up with a massive reporter

that's only going to get bigger as I come up with more options for it and I thought - I need to come up with another way

(to be continued) ....

You can take a unique list as input parameters (item 1 = A, item 2 = 1, item 3 = list (0,0,255.255) ....

But you lose the "user friendy" use of your block

or add a color picker directly in the block

... so I've always admired the variable parameter option in GP (Browser GP) that, IIRC, was programmed up by Jens himself


Now one day, we might get this in Snap! as well but in the meantime, I've come up with this method of just having a multiple inputs parameter as the options parameter

This is what it looks like in the palette
and if no options needed then it can be shrunk

And we can have all these sort of variations

(to be continued)....

i unserstand now... you want somes of your parameters not required (with defaut value)

The main problem with this approach is that fact that a Snapper doesn't know what the optional parameters are as we can't provide text descriptions

My workaround for this is to include the information in the help box
So this lets Snappers know what extra options they can use.

This all good and it just takes a little bit of extra code inside the reporter to read and respond to the options

But since I originally made this block, I've gone onto do other ones and I decided that I really could do with a method of naming the optional parameters

(to be continued)....

This is one of the many reasons we need variadic input groups.

Lisp solves this problem with keyword inputs, so you'd say

(text->costume "A" 1 &border 4)

including any number of the keywords in any order. The block-language equivalent of that would be to have a variadic pair of inputs in which the first one is a pulldown menu of keywords and the second is the corresponding value.

Variadic input groups have been on the list for a long time; we all agree we want this feature. We haven't totally firmed up a design for the UI in the block editor, and other things have been higher priority. But we should think about getting around to this soon.

I think what they're talking about, and what you might be as well, is the "with inputs" text of CALL, RUN, and LAUNCH W/INPUTS that doesn't appear if you don't have them in the block.

That's another reason for variadic groups of inputs.

Was what you were talking about pretty much the [with inputs v] [] of the BYOB 3 RUN, LAUNCH, and CALL?

Wait, didn't you just ask that and didn't I just answer?

In BYOB 3 the "with inputs" is itself an input, but now it isn't.

Edit: This is what I mean:
Screenshot (87)
testing script pic

What about?

Untitled script pic (68)

Oh I see. I'd forgotten that!

I no longer remember exactly why we changed that interface in 4.0. I think at that time Jens was skeptical about the whole idea of dropdowns to change the behavior of primitives. (As opposed to dropdowns to change the target of a behavior, e.g., which sprite or which attribute.)

Since then, though he's gone all in on the idea, as in the LENGTH block that turns into half a dozen other blocks via its pulldown. CALL WITH INPUTS vs. CALL WITH INPUT LIST is less drastic a change than LENGTH vs. JSON! So maybe we should revisit that decision When Things Slow Down™.

We now have several ways to distinguish among alternatives in a family of related functions: the original way, to have separate blocks, e.g,. for +, –, etc.; to have a hidden RELABEL option, e.g., for MOD, MAX, MIN, etc.; and to have an explicit pulldown, e.g., for LENGTH, FLATTEN, COLUMNS, etc. I don't think we have any coherent policy about when to use which. The reasons are partly historical (i.e., how does Scratch do it?), partly aesthetic (is a pulldown ugly here?), and partly a sense of just how related or unrelated the functions are. In retrospect we probably should have chosen RELABEL for the LENGTH block, but that would have been less discoverable.

I guess I made you remember something.

Maybe because no-one would really want a [inputs v]/[input list v] dropdown on all blocks with variadic inputs. (Except for (list [] < >) , (() >), and |script variables ((a)) >|.)

Oh yeah, that sounds right. At first only primitives had variadic inputs, but pretty quickly we added them for custom blocks too, and that required a notation. The red halo around the arrowheads is my fault, btw.

I wonder if Jens had any idea what to use for that.

I think maybe using the arrowheads was his idea -- my contribution was turning the halo red to discourage people from using it accidentally.

so I came up with this reporter


To use it in a simple way - just fill the first slot with the optional parameters that you want to supply to one of of my options slots and it will simply return the list you supply it

Obviously not really useful :slight_smile:

But if you fill in the 2nd slot with a list of optional parameter names you can use it like this

And you get exactly the same result as before but you can use the names of the parameters and only pass in the ones you need.

This emulates other languages that allow for both positional and named arguments

And the result of using this inside of the costume reporter


It looks nicer if I use a color picker of course :slight_smile:

And the relevant code inside my costume reporter now looks like this

So, until Snap! introduces varidic custom reporters, this is my workaround :slight_smile:

Here is the code for my options helper is anyone wants to use it

<blocks app="Snap! 6," version="1"><block-definition s="options %&apos;options&apos; using names %&apos;names&apos;" type="reporter" category="lists"><header></header><code></code><translations></translations><inputs><input type="%s"></input><input type="%l"></input></inputs><script><block s="doDeclareVariables"><list><l>output</l><l>item</l></list></block><block s="doIfElse"><block s="reportAnd"><block s="reportIsA"><block var="names"/><l><option>list</option></l></block><block s="reportGreaterThan"><block s="reportListAttribute"><l><option>length</option></l><block var="names"/></block><l>0</l></block></block><script><block s="doSetVar"><l>output</l><block s="reportMap"><block s="reifyReporter"><autolambda><block s="reportJoinWords"><list></list></block></autolambda><list><l>value</l></list></block><block var="names"/></block></block></script><script><block s="doReport"><block var="options"/></block></script></block><block s="doIf"><block s="reportAnd"><block s="reportIsA"><block var="options"/><l><option>list</option></l></block><block s="reportGreaterThan"><block s="reportListAttribute"><l><option>length</option></l><block var="names"/></block><l>0</l></block></block><script><block s="doFor"><l>i</l><l>1</l><block s="reportListAttribute"><l><option>length</option></l><block var="options"/></block><script><block s="doSetVar"><l>item</l><block s="reportListItem"><block var="i"/><block var="options"/></block></block><block s="doIfElse"><block s="reportAnd"><block s="reportIsA"><block var="item"/><l><option>list</option></l></block><block s="reportListContainsItem"><block var="names"/><block s="reportListItem"><l>1</l><block var="item"/></block></block></block><script><block s="doReplaceInList"><block s="reportListIndex"><block s="reportListItem"><l>1</l><block var="item"/></block><block var="names"/></block><block var="output"/><block s="reportListItem"><l>2</l><block var="item"/></block></block></script><script><block s="doIf"><block s="reportNotEquals"><block var="item"/><l></l></block><script><block s="doReplaceInList"><block var="i"/><block var="output"/><block var="item"/></block></script></block></script></block></script></block><block s="doReport"><block var="output"/></block></script></block><block s="doReport"><l></l></block></script></block-definition></blocks>