Today's vocabulary words
What happens if a custom block or lambda uses a variable name that isn't its own input or script variable?
Most languages designed for kids (e.g., Logo and Smalltalk) use dynamic scope, which means that the interpreter looks at the procedure that called this one, then at the procedure that called that one, and so on until you reach the global variables. This is an easy rule to understand, because if a variable exists, you can use it.
Most modern languages for adults (e.g., Scheme, Javascript) use lexical scope, which means that the interpreter looks at the procedure inside which this one was created, then at the one outside of that, and so on until you reach the global variables. This rule leads to faster compiled programs, and allows the style of OOP explained in section VI of the BYOB 3.1 manual.
Today's Snap! feature
Snap! uses hybrid scope: First it looks in the lexical scope of the procedure, all the way out to the global variables. But if there is no variable by the desired name in the lexical environment, instead of giving an error message, Snap! looks in the procedure's dynamic environment. (More precisely, it looks at the caller's entire lexical environment, then at the caller's caller's entire lexical environment, etc.) This means that if the user is careful not to use the same name for dynamic and lexical variables, they can be combined -- lexical to allow explicit OOP, and dynamic so that an input to the main procedure of a project can be used everywhere without having to be passed down as input to each helper procedure.
Offline
G is a script variable.
Offline
scimonster wrote:
G is a script variable.
There is a script variable named G, and it's in the dynamic scope of the arithmetic computation in C, but there's also a global G (it's set down at the bottom), and global variables are part of the lexical scope of C, so they take priority.
Dynamic scope: C is called by B which is called by A which is called in the global environment.
Lexical scope: C is defined inside A which is defined in the global environment.
In this example only the name DYN is resolved using dynamic scope.
Offline
bharvey wrote:
scimonster wrote:
G is a script variable.
There is a script variable named G, and it's in the dynamic scope of the arithmetic computation in C, but there's also a global G (it's set down at the bottom), and global variables are part of the lexical scope of C, so they take priority.
Dynamic scope: C is called by B which is called by A which is called in the global environment.
Lexical scope: C is defined inside A which is defined in the global environment.
In this example only the name DYN is resolved using dynamic scope.
I don't understand most of this anyways.
Offline
scimonster wrote:
I don't understand most of this anyways.
When I was a high school teacher I used to say "anyhows" to my students in an effort to get them to stop saying "anyways" but it never worked. :-/
You can understand this; it's not as weird an idea as continuations. I'm just not explaining well enough.
Look at the code in the picture. Down at the bottom it says CALL A..., so that means that from top level (where there are only global variables, so we call it the "global environment") we call A. A calls B, and B calls C. So C>B>A>Global is the dynamic environment.
But now, instead of looking at who calls whom, look at where things are defined -- where the lambdas (the THE BLOCKs) are. A's lambda isn't inside any other lambda (or custom block, but we don't have those yet, and anyway those are just another kind of lambda with a slicker GUI). B's lambda is inside A, and C's lambda is also inside A (but not inside B). So C's lexical environment is C>A>Global.
Got that? If not, ask a question.
So, inside of C we're trying to use four variables. For each variable reference, we look first in the lexical environment, then in the dynamic environment. In each environment, we take the first one we find, starting from C's lambda itself.
Lexical environment
C: IN
A: OUT, B, C
Global: A, G
Dynamic environment
C: IN
B: DYN, G, IN
A: OUT, B, C
Global: A, G
In the above, "A: OUT, B, C" means that inside A's lambda there are bindings for variables OUT (an input to the lambda), B, and C (script variables), etc.
So, where do we find G? First we look in the lexical environment. We don't find it in C, nor in A, but we do find it in the global environment, so that's the one we use.
Where do we find OUT? Not in C, but in A.
Where do we find IN? It's right there in C.
Finally, where do we find DYN? It's not in the lexical environment at all, so for this variable only we look in the dynamic environment and find it in B.
(In most programs, the lexical environment is a subset of the dynamic environment. The only exception is when a procedure reports an internally generated procedure:
THE [REPORT [THE ... BLOCK]] BLOCK. INPUT NAMES: FOO
When the reported procedure (the one made by the inner THE BLOCK) is called, its lexical environment will include the variable FOO, but its dynamic environment won't.)
Okay?
Offline
nXIII? Where has he been?
Offline
That's amazing...
Offline
Jens wrote:
the body's first two lines have to say:
if n = 1
report 1
otherwise it keeps stuck in an infinite loop hitting zero and reporting 1.
Wait, why? 0!=1. That's the right base case. If it reports 1, why is there an infinite loop? If it reported factorial(1) or something, that would be an infinite loop.
What am I missing?
EDIT: Turns out to be a Javascript misfeature; Jens is working on it.
Last edited by bharvey (2011-10-17 16:53:16)
Offline
BYOB curlicules:
Offline
This works in BYOB but not in Snap!
EDIT: It's the ()^() block as a variable.
EDIT: Can you add ()^() as a Snap! feature?
Last edited by Hardmath123 (2011-10-18 02:48:48)
Offline