Helper block to supply defaults for variadic option slots

[edit]See post 3 for updated version based on dardoro's modification in post 2

I've a few blocks that have optional options (such as in the MQTT library) and I was getting fed up with having to write boiler-plate code to deal with the slots being expanded or not

Here is the issue
image

If you expand all the options - you get all the defaults
untitled script pic (51)
But if you don't - you get nothing
untitled script pic (52)

But if add in my helper block
image

then you get the defaults even with nothing expanded
untitled script pic (53)

and if you do expand - it merges in any changed values
untitled script pic (54)

The helper block only works if the you name your last variable slot "options" but could be adapted for other uses

I had good fun learning how to use the
untitled script pic (55)
following some help from Brian in another thread:)

Nice idea...


I like the way you managed to get the name of the variable :slight_smile:

But I don't think your for i loop code at the end works in all circumstances

so I'm keeping my initial code in the this version
optionsDefaultExpandsSlotEditor script pic (1)

optionsDefaultExpandsSlotEditor script pic (2)

Yes, the "for" loop is quite pushy

Oh, nice work, both of you!

I love this; I wrote something similar a long time ago in Logo. Berkeley Logo provides eval-twice macros, so the helper can report a list with a LOCAL command (like SCRIPT VARIABLES) followed by a bunch of MAKE commands (like SET). Since it's not a block language I didn't have prompts like "red" etc., but the user could use keywords to choose the inputs to provide. The calling procedure did this:

and the user could say

(The initial 11 with no keyword, if used, is used to set the first input, MAXHARM.)

https://people.eecs.berkeley.edu/~bh/v2ch13/fourie.html

So this is all very nostalgic for me!

How about … ?

Demo

why the empty space in cell A1 of the table?

Imho the reported list should always be of length 4 (in this example), the max number of subslots, with defaults merged in to fill blanks. (If the user doesn't want that for some slot, they'll leave that default empty.)

Yeah, that could be implemented using untitled script pic 317, the exact code depending on what a user would want to get if none of the defaults are specified.

You mean if neither defaults nor actual arguments are provided? Presumably a list of empty strings.

Edit: But I can imagine wanting to have hidden defaults that aren't shown in the block in the palette.

I mean there are 3 relevant quantities:

  1. #options = the number of options (specified by the caller)
  2. #defaults = number of defaults (defined with the custom block)
  3. maxslots = the maximum number of slots (defined with the custom block)

One might have expected both #options and #defaults can’t exceed maxslots, but in Snap! such is not enforced. This does, indeed, create the possibility of having hidden defaults (that will, however, never be prompted).

Continuing this reasoning, I can imagine a systematic approach in which exclusively optional input parameters are used: each ith parameter’s “name” is specified in the ith line of expand, and it may have a default value (specified in the ith line of defaults).

Oh, well, perhaps this is more or less what other were already hinting at.

One thing I wish I could do, which'll never happen, is an input with a default that's entirely invisible, not even an arrowhead, except when the block is used in a recursive call.

I know I can do more or less the same thing using a recursive helper to the user-visible main procedure, but that's unsatisfying when we don't have internal definitions.

Why would you want (to be able) to do that?

Mainly for counting things, or putting them in a list.

(define (reverse lst)
  (define (helper lst result)
     (if (empty? lst)
         result
         (helper (cdr list) (cons (car lst) result))))
  (helper lst '()))

So I want REVERSE to have a hidden input whose initial value is the empty list, but onto which I can cons something on each recursive call. The user of REVERSE should never give a value for RESULT, which should start with an empty list every time the user calls it.