Evaluate Variable inside a Ring?

I would like to create a block that defines a reporter block with a name such as “C Major” that outputs a list of notes such as “[C4] [E4] [G4]”:

image

The defined block should look like this:

image

This is my attempt at creating a block that does this:

However, the actual result is this:

image

Because the variable is inside the ring, it is not evaluated.

Is there a way to achieve the desired result; i.e., reporting the list of notes [C4] [E4] [G4] rather than the variable name “Chord”?

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.

untitled script pic (34)
is this what you’re needing?


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.

PS I didn’t bother creating a “Music” category.

drag this into snap:

I forgot who made this block, but use this

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:

Any of these strategies will create the block Glen is asking for.

BTW, this is a great question and a neat challenge, @glenbull !

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
untitled script pic (7)
because the CHORD variable would, I think, be out of scope inside the ring. But I’ve been wrong before, especially about metaprogramming.

It only works for constant expression. After “define” the expression is losing its original context.




It’s worth to note - does not work for literal.


Combined with the “Metaprogramming” library to be more readable


A modification to make sure only one block of the same name is created (which may or may not be useful)

untitled script pic - 2025-10-10T111535.595

And this variation to save having to use a list reporter

untitled script pic - 2025-10-10T111956.680

That is correct. However, this also will not work:


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)?

I was wondering that too. Is this a new thing?

I think it is a mew bug, and I’m pretty sure I know why it’s there.