# Variable scoping issues on joined blocks

there's no visible difference between the func and join (split (func)), but they behave differently
any variable created outside of the function (globals, script, etc) are no longer available unless using the create variables library

i understand why this might want to be prevented in situations like this, but is tthis isn't just for script variables, it happens to globals too, here a way i can keep global scope variables after manipulating blocks? i want to create macro blocks that can be given to others, and it's not very useful if it breaks code everywhere

Yes, global variables should work. I think Jens has already agreed about that so maybe it'll be in 8.1.

As for local variables, what SPLIT BY BLOCKS does is to turn the function into code. Functions remember the scope in which they were created, but code is just the blocks without an environment. If you want the blocks and the environment, don't split it!

should sprite local variables also work? because if that's the case, then i would reccomend:

• creating a proper (new sprite) block (scisnap primitive doesn't work on the stage, and clones keep hat blocks that can't be removed afaik, so they don't work)
• properly supporting this

because then by creating a new sprite and local variables in it, it's an easy and flexible code sandbox that would REALLY help out with a lot of the metaprogramming i'm trying to do

if there's any discussion on the new sprite block i can create a new thread if that's wanted
(i'd want to discuss hat blocks and local variables somewhat since those would be a bit complicated)

The right way to make you happy would be to make environments (a/k/a scopes) first class, so you could capture whatever environment you want and then hook it up to a piece of code explicitly, saying something like DEFINE (name) (code) (environment). Although really there are two relevant environments, the one to attach to the code and the one in which to bind the name to the created function. So this is the sort of thing we have to work out.

Scheme explicitly does not have first class environments, a decision made because it allows compiled code to run fast. We (so far, knock on wood) don't have that constraint. But it's still not clear that Jens would support first class environments.

In particular, channeling Jens, I think he might note that making sprite environments first class kind of defeats the purpose of sprite-local variables. Which I think is somewhat true but not 100% true.

Stay tuned.

i considered that for a second, but i think snap already has quite a bit of stuff that's nearly inexplicable, and i don't see the point of adding something that could be worked around easily with a bit of cleverness and with features that should probably exist anyways

besides, what really is an environment anyways? are things like position and other sprite properties the same environment, or a different one? shouldn't that be decided with parenting and inheriting? at that point, a sprite IS an environment, and many of the hard questions are gone. if sprites were just slightly more malleable then i think i'd have exactly what i want

Yeah, you're right, I've heard that from Jens too. :~) Being as I am a Schemer, I think of environments as just about variables (which includes procedure names, because Scheme has only one namespace and procedure values are bound to names the same way numbers are bound to names).

But yeah, sprites have more things that should be considered part of their environment. We wouldn't have to decide where to draw the line anew for this feature; the Snap! internal data structure that represents a sprite has already made that decision. In fact, you could argue that we already have first class environments, because we have first class sprites!

Scripts created using join are "unbound rings", a.k.a "just code". They need to be bound to an environment before they can access variables. I think this is already explained in the manual. Nothing special about whether the environment is global or any other scope.

How do you bound them to an environment?

the sensing "of" block

"Bound" is the past participle, like "eaten" or "copied." The present tense is "bind."

I think that you would use CALL.

No, the (first) input to CALL has to be a procedure, which is made of two parts, the code and an environment. OF, as suggested by @bombmanyeeted, combines the code (first input) with the environment from a sprite (second input), containing that sprite's local variables as well as the global variables.

Whoops, sorry, forgot.

Ok.

i don't see anything in the manual about rings being unbound or how to bind them, "bind" and "bound ring" aren't anywhere in the manual

i still can't figure out how i'm supposed to bind anything, this is way too vague.
from what i can tell, if i get variables of a ring, it gives the sprite and script variables it can access, not the parameters, and it doesn't seem to be able to set anything. it errors if the ring is created with join.

EDIT: figured it out from bh and the block's help text, would be nice to have it in the manual somewhere (if it isn't) since this is pretty hard to find

It's explained - somewhat tersely - in the "Macros" chapter of the manual on pp. 105

Yeah, we need better documentation. I got that chapter written just barely in time for the 8.0 release. :~)

Prior to the metaprogramming features, we didn't really have to talk about environments because making a ringed procedure automatically attached the right environment and everything just worked without the user worrying about how it worked. But now, with SPLIT, you can separate the code from the environment in which it was defined, so that later you can attach that code to a different environment if you want.

We considered inventing some other visual representation for code without an environment attached, purple rings or black-and-white-striped rings or something, but we decided that would just scare people away.

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