Just saying, you can right click a script and click “script pic” to download a picture of the script (with a transparent background). What’s even cooler is that you can drag and drop script pics into snap and get the script back (even with all custom blocks used in the script).
What you’re trying to do needs sometaprogramming to generate a list block with the same values as the list.
However, there is no reason to go the approach you are going. What you’re trying to do is use custom blocks as variables, which is not a very good approach, as they are much slower (especially when setting them to a different value). You’re much better off just setting a variable (or dare I say, creating a variable with the create variables library) than creating a custom block.
I had a different approach from the one @mctx_studios used. The key to making this work is that the input CHORD is declared to be of type “Any (unevaluated)” so that it enters the script with a ring around it. Then, so that you get the actual input list instead of a “CHORD” variable block, put the DEFINE in a RUN WITH INPUTS so that the input expressions are evaluated in the procedure’s scope and not the inner ring’s scope. And finally, since the upvar BLOCK isn’t in the procedure’s scope, the ringed script has to copy it to a script var that is in the right scope.
Nice! Using an unevaluated input is a neat trick. As @sathvikrias points out, the definition can be formulated a little bit more concise, - let me show you yet an even shorter version that gets rid of explicitly setting the block’s type -
The slight downside with this method is that the chord slot on the “outside” of the block doesn’t indicate that it’s expecting a list.
Alternatively you can use metaprogramming to simply create a list-block with the given values. This probably sounds harder than it is. Basically all you need to remember is that you start with a fully collapsed list block and join it with a list of items that is pre-pended with how many slots you want to expand it to:
Thank you all so much! Not only did I get the immediate block that I needed, but in the process, I learned a lot. Thank you not only for the answer, but also for the accompanying explanations that unpacked the underlying reasons.
The slight downside with this method is that the chord slot on the “outside” of the block doesn’t indicate that it’s expecting a list.
Yeah, I know. This is why “unevaluated” should be a checkbox in the dialog that can be applied to any type. :~) That would give us two slots in the type array to bring back Object or whatever. (Of course it’d also destroy my elegant arrangement of the types so that the bottom row is unevaluated versions of the rings in the row above.
Why are you using run? As far as I can tell you can just drag the Chord variable directly onto the definition ring and the variable will absorb the ring - leaving you with an unringified variable that will be evaluated right off the bat. This seems to work fine for me:
Your way would work if you’re using Jens’s shortcut of putting an expression rather than a script in the last input slot of DEFINE to imply that the new block is a reporter and has a REPORT _ block around the expression. (And I unintentionally did that too; I meant to use an explicit REPORT block, as in Glen’s original version, but goofed and was lucky. :~) ) If I did have a REPORT block in that last input to DEFINE, then it wouldn’t work to say
because the CHORD variable would, I think, be out of scope inside the ring. But I’ve been wrong before, especially about metaprogramming.
The “chord” variable’s value will not be passed to the report block because it is in a ring (only empty rings are filled). Moreover, even if this did work, the block would report ((list [C4] [E4] [G4] @<>)@>) not the list itself because “chord” is unevaluated.
PS: @ego-lay_atman-bay, what happened with the snapblocks above (gap between list block and ring)?