Set/change list element

Is this the best way to do like "a_list[i]+=1"?

Seems quite awkward. I'd want to be able to drag that (item) block into a [set] or [change] block, but the variable dropdown doesn't accept expressions/blocks.

If I make a custom block like [set (list) [ (i) ] = [rhs] ], would that be a significant performance hit?

That would be fine. There's always a small cost per procedure call; whether it's "significant" depends on how often you do it, compared to doing other things.

We inherited the imperative list operations from Scratch. We're not especially eager to make imperative programming smoother; we prefer that you program functionally, using HOFs to make modified copies of lists. But we're not going out of our way to make it hard either.

we prefer that you program functionally, using HOFs to make modified copies of lists

So what would that look like? For the pandemic simulation from BJC, the way we're extending it in class is to have additional states, 1=well, 2=infected(asymp), 3=sick, 4=hosp, 5=died, 6=recovered. At the end of every iteration, I want to create a list of counters, loop through the clones, and increment the counter for that clone's state.

Also, if I were to loop through the counters and [tell] them each to increment a counter in a global, or broadcast a message to trigger them to increment a global counter, would they get in each others' way? Are clones threaded, and global variable setting protected with mutexes?

It would look like a recursive call, with that list as input. There wouldn't be any global (or sprite) variable pointing to it; each "round" of the simulation would be a separate computation.

But I didn't mean to suggest that you have to do things that way. Just that our efforts aren't going into syntactic sugar for list mutation.

About mutexes, we don't need mutexes per se, because we have our own scheduler, which switches between threads only when a thread explicitly yields, which it does at the bottom of the primitive looping constructs. In particular, there is never a yield between the test part of an IF block and the sub-script that it controls.

There's a different possible issue about event-driven scripts (i.e., ones that start with a WHEN block): What if the same event happens again while such a script is running? We have two answers to that question: The one we inherited from Scratch, which is to stop the partially-done script and start it again from the top. This does break scripts that put state variables into an inconsistent state part way through, but we keep this option to support the particular case of generating music; if a sound hasn't finished when the event triggers again, it's better to drop the end of the sound and keep on the beat. But if you're doing database-ish stuff, you can check "Thread safe scripts" under the gear menu, and then the second event is dropped on the floor, so that the first time through the script can finish.

Of course the right thing is to keep the second event in a queue until the first one finishes. We've talked about having that as a third option, and about being able to set the option per-script rather than globally, but we haven't done either of those things so far.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.