jmoenig / Snap

a visual programming language inspired by Scratch
http://snap.berkeley.edu
GNU Affero General Public License v3.0
1.5k stars 744 forks source link

inconsistencies in behavior of sprite-local variables and clones #2307

Open brianharvey opened 5 years ago

brianharvey commented 5 years ago

This comes from a user report in the forum, but the behavior I see is different from what he sees.

  1. Make a sprite-local variable. Then, in the sprite corral, clone the sprite. The child gets a copy, not a ghosted shared variable.

  2. Make a new sprite without a parent. Then, in the sprite corral, change its parent to the first sprite. The newly-adopted child does get a shared variable.

This is already wrong, I think; the child should share the parent's variables no matter how it became a child.

I can't reproduce the behavior in which the user gets multiple copies of the same variable at once.

jmoenig commented 5 years ago

that's exactly how I want it to be. The first point - shadowing local vars when you clone a sprite ensures compatibility with the Scratch way of cloning sprites that Snap has had for many years. The second one is new so we simply inherit.

brianharvey commented 5 years ago

Dammit, remember when you copied the incorrect Scratch "cloning" those many years ago, and I yelled at you, saying that down the road when we tried to get it right, you'd say we can't because users already expect the wrong behavior, and you pooh-poohed me? Well, here you are doing it!

We should never have had Scratch-style copying-and-calling-it-cloning, and we shouldn't have it now. It's an abomination. It totally ruins our claim to object-orientation.

Please, from now on, when Scratch invents something, DO NOT implement it in Snap! without my explicit permission.

jmoenig commented 5 years ago

See, I insist that avoiding automatic inheritance in clones is good, even right, if the cloning happens programmatically instead of in the GUI. The whole inheritance gimmick is problematic - both classical and prototypical - because you hardly ever use it in the Aristotelian manner of describing hierarchies of species, but mainly to link objects in other ways, say, for what they call "data bindings".

Scratch kids - and almost every Snap kid I've ever seen will start programmatic cloning using a pattern of looping over the original sprite to change it slightly, and then - when it's in the desired state - clone it. And they - I think rightly - expect the clones to reflect that state of the "original" at the time of cloning. The pattern kids - and most adults - follow is something like this:

grid of clones script pic

If we did it your preferred way this pattern that every Scratch kid follows would no longer work, and every sprite would end up saying the exact same numbers - the last ones set to the original. Instead of letting kids explore and discover inheritance we would end up having to explain about shadowing variables first thing. I'm not convinced about the pedagogical benefits of that.

Forcing novices to use tell and ask is yet another complicated step that I would love to avoid in the interested of supporting them with what they already know. I also insist that the sheer beauty of Snap's current design is that we have a single model of clones, so you can, when you want and when you're ready, use clones with tell, ask, and inherit.

This is quite different - I maintain - from when someone creates a single clone using the GUI. In that case they're probably not creating a "tribe" but modeling one of those "links". That's one of the reasons why I think that both indiscriminate "Eisenbergification" and insisting on "consistent" inheritance is not ideal for real users.

Inconsistencies are an indicator of a design issue, I agree. But sometimes doing what the user expects beats the desire to be consistent, sometimes it's right to distinguish. You taught me that when you insisted that automatic un-ringification of variable blobs is the right thing for users - most of the time - even though it's totally and utterly inconsistent.

brianharvey commented 5 years ago

Wait, I think we're thinking about two different things. In this issue programmatic cloning is not involved. It's two different GUI operations: Setting the parent of an existing sprite vs. cloning a sprite in its context menu. So I need to hear why those two cases should be different.

You're quite right about your example. In BYOB 3.1 we carefully considered every property of a sprite and decided which ones the user would expect to be shared. I thought that this time around we'd agreed that that was too complicated, and everything would be shared.

I still want to be able to tell people a simple story. Maybe the right answer is that nothing is shared by default, everything is copied, and you have to use INHERIT for the things you want to inherit. That's sort of the opposite of what I thought we'd agreed on, but like the inherit-everything policy it has the great virtue of simplicity. The user doesn't have to read Jens's mind to know what's shared.

Obviously we need a discussion of this f2f, or at least Facetime2Facetime, starting from the beginning. If you convince me that there are different things users want that we can figure out, maybe we have to change the name of something away from "clone."

jmoenig commented 5 years ago

I believe the current way of Snap is perfect. If nitpicks take issue with that assigning a parent to an existing sprite - thus making it a "clone" - is inconsistent I'll take out that feature altogether. We didn't have it in BYOB and it's just something I think is fun to show occasionally.