Reputation: 23976
Logo is the first programming language I ever learned as a child. I recently found out that Logo supposedly uses dynamic scoping, which came as a surprise to me because I always thought it just used global variables. This made me wonder if perhaps I didn't understand what dynamic scoping meant.
I thought that with dynamic scoping, a variable would go on a global stack, so then when you called another method the variable would still be visible. (So far, like a global variable.) Then, if you declared a new variable with the same name, this would be pushed on the global stack, hiding the original variable. (At this point, still not much different than assigning a new value to a global variable.) And lastly, when you exited the method, that new assignment would be popped off the stack, and the variable would revert to its original value. (This seems like the key part that makes it dynamic scoping, as opposed to just reassignment of global variables.)
So having heard that Logo used dynamic scoping, I expected this program:
to test1
make "x "foo
print (se [In test1: ] :x)
test2
print (se [Back in test1: ] :x)
end
to test2
print (se [In test2: ] :x)
make "x "bar
print (se [Still in test2: ] :x)
end
test1
to have this output:
In test1: foo
In test2: foo
Still in test2: bar
Back in test1: foo
But when I run it in FMSLogo, it actually has this output:
In test1: foo
In test2: foo
Still in test2: bar
Back in test1: bar
This actually matches what I remember from when I was a kid, and is consistent with what I'd expect if there's a single global variable named x
. But I don't see how this is dynamic scoping -- the variable never goes out of scope!
So why do references, like this one for instance, claim that Logo uses dynamic scoping?
Upvotes: 3
Views: 284
Reputation: 700592
Logo does have dynamic scoping, but your example doesn't have a local variable, so in the variable set in the test2
function is the global. You would need to use the local
keyword instead of the make
keyword to create a local variable.
This should demonstrate the dynamic scoping:
to test1 :x
test2
end
to test2
print (se [In test2: ] :x)
end
make "x "foo
test2
test1 "bar
If I got it right (about two decades since I wrote any Logo), it should produce:
In test2: foo
In test2: bar
Calling the test2
function directly uses the global variable, but when called from test1
it will use the parameter that passed into test1
instead of the global variable.
Upvotes: 3