Design decisions around commands vs reporters

Does using ask () for ({}@addInput) @addInput have any technical advantage in this situation over tell () to ({}@addInput) @addInput?

Tell is hyperized in a weird sense - it behaves like ask. This will not error and will hide all the sprites:


For some reason, tell is hyperized in a funky way that requires the script to report something. I then tried the alternative (non-JavaScript) definition of tell, and it errored the same error: "reporter didn't report". Adding a report block had the same effect. I was able to determine from this that there is a similar weird hyperization of run:

The say block runs, and then the run block errors. I think that this behaviour is a bug, and based on your post I'm guessing that tell and run are not supposed to be hyperized at all.

Hmm, "supposed." In the beginning, it was a rule that only reporters were hyperized (and not even all reporters); later, though, some command blocks were added one by one. I think the least restrictive rule would be "A block isn't hyperized if it already has a meaning for a list as input." Thus, = isn't hyperized; ITEM isn't hyperized in general, although some list formats (in the first input) have quasi-hyperized meanings.

At one point it seemed to me that you were operating under that rule. But here you seem to believe in a more restrictive rule. One could, for example, argue that a list input to RUN (and perhaps also a list as the second input to TELL) should be understood as a syntax tree (what you get from SPLIT BY BLOCKS).

But I confess that I can't offhand see a downside to hyperizing the first input to TELL.

jens?

Yes, I meant Jens. But he tells me it's not true that we've been hyperizing bunches of commands. I coulda sworn... :confused:

the only command block that I've experimented with hyperizing - in a very special way - is CHANGE VARIABLE BY (hyper-mutation). And that's a very special case for exploring neural networks in Snap!. In general the rule is that only reporters ever get hyperized, and that most reporters already are, but no commands.

i don't understand the point of the reporter/command distinction besides what slots it's easier to put in. custom reporters are built from stack blocks, c slots in custom blocks can contain reporters, the REPORT block itself is a stack block that reports, many projects have to use a custom "ignore" block to use reporters like commands, etc.

in my own coding experience, most of the work is performing a bunch of operations with reporters and basic control flow blocks to figure out where to put a sprite at the end. commands with any visible effect don't play a particularly large role. by the time i use RUN, LAUNCH, or TELL, i've already used a ton of reporters and CHANGE. all i see is that they don't behave how i expect, and the error message immediately points to a workaround (empty report) that would have no issues working if it were hyperized properly.

my projects already rely on the current buggy hyperization, i think it would just make more sense to actually hyperize them.

there's a few other commands that could potentially be hyperized.

  • play sound/note/frequency, and even set instrument could all be made to play multiple sounds at the same time, although multiple notes would be awkward for most cases like that and playing a list of numbers as a sound already means to make a sound from samples.
  • the broadcast block could do multiple broadcasts at once.
  • paste on and cut from could operate on multiple sprites.
  • create clone could clone multiple sprites. the existing "new clone of" reporter currently doesn't work on a list, it does nothing, reports nothing, and freezes if you try to use the nothing result.

Personally, I think a lot of command blocks should be able to be used as reporters. I often find myself making a version of delete item ( v) from @list::list and similar blocks into a reporter, where it does the action and reports the resulting list. Maybe I'm just too used to Javascript, though.

Some languages have different names for procedures that return a value (e.g., "function") and ones that don't (e.g., "procedure"); other languages have every procedure report a value (which might be a distinguished "no value" value). No question (in my mind anyway) that the Lisp-like languages in which all procedures return values are easier for an experienced programmer to use.

But our heritage (from Logo by way of Scratch) is a syntax design for kids, including kids who haven't studied high school algebra yet, and therefore have no idea what a function is. In that context, the received wisdom says that it's easier to understand what a program means if we make a distinction between commands and reporters.

So you should count your blessings, such as that we let you define custom reporters at all! :~)

Umm. Technically, the REPORT block doesn't report. What it does is cause its caller to report a value.

There do exist languages that make a distinction between commands and reporters, but allow a reporter in tail position in a stack (e.g., as the last instruction) to imply REPORT.

If I were designing a language just for myself to use, all blocks would be reporters-with-tabs so you could stack them or embed them in other blocks' input slots. That would be the same as Scheme syntax. But I'm still not convinced that that's the right thing for beginners.

Yes, we could have an "implicit REPORT" option. Nobody has suggested that, so far, and anyway Jens doesn't like runtime options because he wants Snap! to be super fast. :~) If I did want such a feature, I would propose that dragging a reporter under a script would actually put a visible REPORT block around it.

I'll let Jens answer the part about your proposed expansion of hyperblocks to commands. I mean, he did answer it, as a question about what Snap! does now, but he hasn't explicitly said that he thinks that's the best solution.

My feeling is that users already have enough trouble understanding that some blocks mutate their list inputs while others don't. Even teachers keep making "bug reports" about a list changing or not changing unexpectedly. As I said recently in another thread, this is why, even though I want a less mysterious name for MAP, it's still called MAP because I haven't found one that doesn't suggest mutation.

I still don't really understand what MAP does
Personally, I think there should be a hidden option behind an arrow that's a T/F input with it defaulting to true (on some blocks, obviously MAP isn't the best example). If it is true, it mutates the list. Basically, (map ({} @addInput) over @list @delInput mutate? <t> ::list)

Whoa, really? It takes a function, let's say a function whose domain and range is numbers, such as SQRT, and a list of values in the domain of the function (so, numbers in this example). It creates a new list, the same length as the input list, in which the nth item is the result reported by calling the function with the nth item of the input list as its input.

Ohhhh, okay that makes sense. I typically would've used a for-each loop for that. Personally, I think there could be a more descriptive name, though none really come to mind

Ah, no, no! The goal in this enterprise isn't to minimize the number of blocks by cramming a lot of different functionalities into each one. The goal is to understand what ideas are hard for novice programmers, and to separate them out to clarify that they're not the same thing. And, trust me, whether something mutates or not is a big stumbling block for novices.

Yeah, that's what I said! :~)

This does bring up some questions. Currently, the call block is hyperized such that it runs each of its inputs in order. In this example, the sprite will never "say" anything:


However, in the case of tell, this is unlikely to be what the user wants. Take this as an example (report added so the script actually works in current Snap!):


In this example, what is probably intended is for all the sprites to move in a circle at the same time, not individually in the order they appear in the list. What they probably want is something like this:


Wait a minute! One of the cool things about tell is that your script resumes once tell is done, not right away! So, we should really be keeping track of when the scripts finish so that we can resume after they are done:

Alright, we've finally got everything sorted, right? Nope. What if we're dynamically creating and/or deleting sprites? Then our script will get completely messed up. Alright, here is what we have to do:

Wow. That was complicated. Personally, I'd much rather just import the parallelization library:

In any case, this brings up some important questions about the hyperization of the tell block. Should it be consistent with call, or should it start a new thread for each script and wait for them to finish? Just pointing out the complications of hyperizing commands ;~).

untitled script pic (6)

I feel that this is even more confusing. if I look up a MAP function for python or whatever the documentation for that programming language mostly aligns with snap!'s MAP block.

here's my idea: (apply function (() @addInput) to @list ::list)

In a previous similar discussion:

So I'm guessing that @bh would say the same to your idea...

i didnt see that, i just skimmed through the topic to get a general idea of what was going on :sweat_smile:

No, it was a different discussion about the same thing. Sorry!