I'm trying to create a group of clones where each clone has a variable that points to the next clone that's created - essentially a linked list. I have a local sprite variable called
_child which I want to store the next clone when it's created. There's one sprite (called
Proto Clone Test) that walks through the list and tries to append a new clone to the end of the list.
However, when trying to append the new clone to the list, it looks like it always sets the
_child variable of
Proto Clone Test instead of the
_child variable of the last clone in the list. I'm using the
Tell block so I'd think it's set the
_child variable of the last cloned sprite, but it doesn't seem to be doing that.
Here's the link to my test project: https://snap.berkeley.edu/project?user=tgsnap&project=clone-test
The space bar starts the clone script. Since I created a minimal project to duplicate the issue, you have to drag the newly created clone away from (0, 0) to see the new ones.
Thanks for any help!
Hi Tim, welcome to Snap!
Here's a little minimal project I just made to show how you can make a double-linked list (a "chain") of clones. Maybe that helps: https://snap.berkeley.edu/project?user=jens&project=chain%20of%20clones
Thanks Jens. Your example did help me finally figure out what the issue was. The attribute reporter block has some unexpected subtlety. I dragged the local variable I wanted into the block. I finally realized that the variable wasn't colored blue with the triangle drop-down indicator, as in your example, but was colored orange. I also had to trick the attribute reporter block into letting me select the variable properly, by dragging the actual sprite into the
of side of the block so I could select the variable via the drop-down. Then I replaced the
of side of the block with the local script variable. I don't think this workaround is in the documentation?
Also noticed some unexpected behavior when
telling my clone to print its name. It printed the name of the object that created the clone, instead. If I understand things correctly, I thought it should use the name of the clone when you pass it a script with
tell? It worked when I used the attribute reporter block, instead. Screenshot below:
I updated my project link with the working code.
Thanks again for the help,
I still don't understand why it didn't work. I spent a few hours banging my head against it; I guessed that there was a timing problem between the TELL and the block after it, but that wasn't the problem.
You shouldn't have to use the official NAME property of the clone. myName is a sprite-local variable, and the TELL script should use the target's version of it. Maybe @jens could explain that to me?
P.S. I hate camel case! Variables in Snap! can have spaces in their names, so "my name" is the approved name for that variable.
dunno what the design with all the naming was here, but having both a sprite-local variable and a same-named attribute "name" is asking for conflicts to happen somewhere down the line.
I was assigning a "name" just for debugging purposes. The first version used
myName but I shortened it to
name when creating a new sprite to try appending to the list a slightly different way. Didn't think about colliding with an official property. Renamed
id, but same issue remains.
Yeah, the myName version already doesn't work, so I don't think conflicting with an attribute name is relevant.
@jens: We have way too many attributes with commonly-used names to get away with making them reserved words. Are you really going to tell users they can't have a variable named "left"?
What about a special indicator in the drop-down menu for local variables? That way, they can have the otherwise conflicting variable names.
Also, wondering why
c for its
child doesn't seem to work. That seemed to be the more obvious block to use as a new user. I also tried
child in the
ask block, but then it goes into an infinite loop.
Kudos to the support you're offering, especially given that you're responding on the weekend!
there is no technical name conflict between variables and attributes, only a possible "mental" one
I'm not really sure what the original project was exactly supposed to do that didn't / doesn't work?
this should work, I think.
This doesn't work, however (using the
ask block to get
child instead of the
attribute reporter block).
c never gets the child sprite when using
ask. So when entering the
repeat block, it only executes once no matter how many clones were created. Everything works fine when using the
attribute reporter block, instead.
The issue discussed in this thread is
say id doesn't print the correct value of the clone, but
say id of clone does. Screen shot is from yesterday where I used
name instead of
I've made a minimal (I think) test case. Make a second sprite. In sprite(2), make a sprite-local variable foo. Give it a nonzero value.
Now, back in sprite 1, do this:
You'll get 0. Now separate the two blocks and click the SAY alone. You'll get sprite(2)'s foo.
That's certainly defensible; with the two blocks together, the SAY is in the scope of the script variable.
Now, in sprite 1, make a sprite-local foo and give it a value different from that of sprite(2)'s foo. Click the SAY (without the SCRIPT VARS). You'll get sprite 1's value, not sprite(2)'s value. I think this is a bug, @jens.
You're right. This does look like a bug, indeed. Thanks! Investigating...
I'm not quite following how this is equivalent to the original problem. I think the original problem was that the assumption that these two blocks are equivalent:
Are you saying that the ringified variable name is being shadowed by either a script variable or a script-local-variable in the invoking sprite? I didn't know you could use a ringified variable name like that.
So, first of all, about ringification: As usual in Snap!, inputs are evaluated before a block is run. So, when you say SAY (2+3), all SAY knows is that its input value is 5. Similarly, if you said ASK (C) FOR (CHILD) without a ring, CHILD would be evaluated in the calling sprite before ASK happened. This is why the ASK block has a built-in ring, because it's always what you want; you're using ASK because you want to know the other sprite's values, not your own. However, Snap! has the rule that if you put a variable in a ringed input slot, the ring disappears. That's because in almost all contexts, the variable is a Procedure-valued input, and you want to run that procedure, not the variable itself. ASK and TELL are exceptions, and maybe it'd be better if we made them exceptions to the rule about unringing variables -- except that when we try too hard to "do what I mean," users get confused. (Footnote: "Do What I Mean" was the name of a '60s early-AI program by Warren Teitelman that corrected users' typing errors. When the system was about to give an error message, it would look for near-miss names and similar mistakes, and it would correct them.)
And, yes, the ringified name is being shadowed. Shadowing with a script variable is correct, because the ASK is still part of the same script. But shadowing with a sprite-local variable in the invoking sprite is a bug in Snap!. If you wanted the invoking sprite's variable, you wouldn't use ASK in the first place! And if you want to use the invoking sprite's variable as part of a larger expression that should otherwise be evaluated in the target sprite, you use the arrowhead on the ASK to make it
The OF block is different. It gives you a menu of all the things you can ask the target sprite (or other first class object) for, and it doesn't get shadowed by anything, not even script variables. You can also ask it for the other sprite's local methods (blocks) and then CALL or RUN them.
Fixed for the upcoming minor release, thanks!
Great, sorry for causing so much trouble over the weekend!