I am trying to understand how CoffeeScript variables are scoped.
According to the documentation:
This behavior is effectively identical to Ruby's scope for local
variables.
However, I found out that it works differently.
In CoffeeScript
a = 1
changeValue = -> a = 3
changeValue()
console.log "a: #{a}" #This displays 3
In Ruby
a = 1
def f
a = 3
end
puts a #This displays 1
Can somebody explain it, please?
Ruby's local variables (starting with [a-z_]) are really local to the block they are declared in. So the Ruby behavior you posted is normal.
In your Coffee example, you have a closure referencing a. It's not a function declaration.
In your Ruby example, you don't have a closure but a function declaration. This is different. The Ruby equivalent to your Coffee is:
a = 1
changeValue = lambda do
a = 3
end
changeValue()
In closures, local variables present when the block is declared are still accessible when the block is executed. This is (one of the) powers of closures!
The a variable being used inside the changeValue function is the global a variable. That CoffeeScript will be compiled into the following JavaScript:
var a, changeValue;
a = 1;
changeValue = function() {
return a = 3;
};
changeValue();
console.log("a: " + a);
In order for changeValue to not alter the a variable (i.e. use a local variable), you would either need to have an argument to the function named a (which would create a as a variable local to that function) or declare a as a local variable inside the function using var a = 3; (not sure what the CoffeeScript for that would be, I'm not a CoffeeScript guy).
Some examples of JavaScript variable scope.
Related
NB: I am using Lua version 5.3.
This question is motivated by Exercise 25.1 (p. 264) of Programming in Lua (4th ed.). That exercise reads as follows:
Exercise 25.1: Adapt getvarvalue (Listing 25.1) to work with different coroutines (like the functions from the debug library).
The function getvarvalue that the exercise refers to is copied verbatim below.
-- Listing 25.1 (p. 256) of *Programming in Lua* (4th ed.)
function getvarvalue (name, level, isenv)
local value
local found = false
level = (level or 1) + 1
-- try local variables
for i = 1, math.huge do
local n, v = debug.getlocal(level, i)
if not n then break end
if n == name then
value = v
found = true
end
end
if found then return "local", value end
-- try non-local variables
local func = debug.getinfo(level, "f").func
for i = 1, math.huge do
local n, v = debug.getupvalue(func, i)
if not n then break end
if n == name then return "upvalue", v end
end
if isenv then return "noenv" end -- avoid loop
-- not found; get value from the environment
local _, env = getvarvalue("_ENV", level, true)
if env then
return "global", env[name]
else -- no _ENV available
return "noenv"
end
end
Below is my enhanced version of this function, which implements the additional functionality specified in the exercise. This version accepts an optional thread parameter, expected to be a coroutine. The only differences between this enhanced version and the original getvarvalue are:
the handling of the additional optional thread parameter;
the special setting of the level parameter depending on whether the thread parameter is the same as the running coroutine or not; and
the passing of the thread parameter in the calls to debug.getlocal and debug.getinfo, and in the recursive call.
(I have marked these differences in the source code through numbered comments.)
function getvarvalue_enhanced (thread, name, level, isenv)
-- 1
if type(thread) ~= "thread" then
-- (thread, name, level, isenv)
-- (name, level, isenv)
isenv = level
level = name
name = thread
thread = coroutine.running()
end
local value
local found = false
-- 2
level = level or 1
if thread == coroutine.running() then
level = level + 1
end
-- try local variables
for i = 1, math.huge do
local n, v = debug.getlocal(thread, level, i) -- 3
if not n then break end
if n == name then
value = v
found = true
end
end
if found then return "local", value end
-- try non-local variables
local func = debug.getinfo(thread, level, "f").func -- 3
for i = 1, math.huge do
local n, v = debug.getupvalue(func, i)
if not n then break end
if n == name then return "upvalue", v end
end
if isenv then return "noenv" end -- avoid loop
-- not found; get value from the environment
local _, env = getvarvalue_enhanced(thread, "_ENV", level, true) -- 3
if env then
return "global", env[name]
else
return "noenv"
end
end
This function works reasonably well, but I have found one strange situation1 where it fails. The function make_nasty below generates a coroutine for which getvarvalue_enhanced fails to find an _ENV variable; i.e. it returns "noenv". (The function that serves as the basis for nasty is the closure closure_B, which in turn invokes the closure closure_A. It is closure_A that then yields.)
function make_nasty ()
local function closure_A () coroutine.yield() end
local function closure_B ()
closure_A()
end
local thread = coroutine.create(closure_B)
coroutine.resume(thread)
return thread
end
nasty = make_nasty()
print(getvarvalue_enhanced(nasty, "_ENV", 2))
-- noenv
In contrast, the almost identical function make_nice produces a coroutine for which getvarvalue_enhanced succeeds in finding an _ENV variable.
function make_nice ()
local function closure_A () coroutine.yield() end
local function closure_B ()
local _ = one_very_much_non_existent_global_variable -- only difference!
closure_A()
end
local thread = coroutine.create(closure_B)
coroutine.resume(thread)
return thread
end
nice = make_nice()
print(getvarvalue_enhanced(nice, "_ENV", 2))
-- upvalue table: 0x558a2633c930
The only difference between make_nasty and make_nice is that, in the latter, the closure closure_B references a non-existent global variable (and does nothing with it).
Q: How can I modify getvarvalue_enhanced so that it is able to locate _ENV for nasty, the way it does for nice?
EDIT: changed the names of the closures within make_nasty and make_nice.
EDIT2: the wording of Exercise 25.3 (same page) may be relevant here (my emphasis):
Exercise 25.3: Write a version of getvarvalue (Listing 25.1) that returns a table with all variables that are visible at the calling function. (The returned table should not include environmental variables; instead it should inherit them from the original environment.)
This question implies that there should be a way to get at the variables that are merely visible from a function, whether the function uses them or not. Such variables would certainly include _ENV. (The author is one of Lua's creators, so he knows what he's talking about.)
1 I am sure that someone with a better understanding of what is going on in this example will be able to come up with a less convoluted way to elicit the same behavior. The example I present here is the most minimal form I can come up with of the situation I found by accident.
local function inner_closure () coroutine.yield() end
local function outer_closure ()
inner_closure()
end
The function make_nasty below generates a coroutine for which getvarvalue_enhanced fails to find an _ENV variable; i.e. it returns "noenv"
That's a correct behavior.
The closure outer_closure has upvalue inner_closure but doesn't have upvalue _ENV.
This is how lexical scope works.
It's OK that some closures don't have _ENV upvalue.
In your example the closure inner_closure isn't defined inside the body of outer_closure.
inner_closure is not nested in outer_closure.
It's impossible.
If a closure doesn't make any use of the global environment _ENV, then it doesn't have that upvalue whatsoever.
A function like
local something = 20
local function noupval(x, y)
return x * y
end
Doesn't need or have any upvalues, not even to the global environment.
This question implies that there should be a way to get at the variables that are merely visible from a function, whether the function uses them or not.
There really isn't though. You can easily confirm this by looking at the output of luac -p -l <your_code.lua>, more precisely at the upvalues of each function.
If anything, I think using the word visible is somewhat misleading there. Visibility really only matters when creating a closure, but once it has been closed, that closure only has a set of upvalues which it can access.
Exercise 25.3: Write a version of getvarvalue (Listing 25.1) that returns a table with all variables that are visible at the calling function. (The returned table should not include environmental variables; instead it should inherit them from the original environment.)
You may have misunderstood that exercise; the way I understand it is something like this:
local upvalue = 20
local function foo()
local var = upvalue -- Create 1 local and access 1 upvalue
type(print) == "function" -- Access _ENV so it becomes an upvalue
return getvarvalue_enhanced()
end
and the above would return {var = 20, upvalue = 20, _ENV = <Proxy table to _ENV>}
After all, it asks specifically about the calling function, not one you pass as a parameter.
This doesn't change the fact that you still only get _ENV if you access it though. If you don't use any globals, the function won't have any reference to _ENV whatsoever.
When I ran the Julia code below, there was an error: UndefVarError: globalValue not defined.
I thought that the globalValue is a global variable, but it is not. Thus, if I add the command "global globalValue" inside the for loop, my code will work. So, could anyone please have a look at it let me know what happened? Thanks in advance!
globalValue = 1.0;
tempValue = 0.1;
for ii = 1:10
# global globalValue; if I add this command, my code will work
tempValue = 5.0; ## I have a function to update "tempValue"
if globalValue < tempValue
globalValue = tempValue;
end
end
It seems you are on Julia >= 0.7, where the scoping rules have changed.
Long story short, in a local scope, such as your for-loop, global variables are only inherited for reading but not for writing. There are two ways around it:
put an explicit global in front of the assignment (what you figured out yourself)
wrap everything in a "global local scope" like let ... end block (globalValue isn't really a global variable anymore)
In your case, the second option would look like
let
globalValue = 1.0;
tempValue = 0.1;
for ii = 1:10
tempValue = 5.0;## I have a function to update "tempValue"
if globalValue < tempValue
globalValue = tempValue;
end
end
end
You can find more information here:
https://discourse.julialang.org/t/repl-and-for-loops-scope-behavior-change/ (in particular this post by Stefan, who is one of the authors of Julia
https://docs.julialang.org/en/stable/manual/variables-and-scoping/#scope-of-variables-1
Although I find this a bit annoying myself, there are good reasons for why the change has been made. Also, on should try to avoid changing globals anyway. Let me quote the manual here (see link above):
Avoiding changing the value of global variables is considered by many
to be a programming best-practice. One reason for this is that
remotely changing the state of global variables in other modules
should be done with care as it makes the local behavior of the program
hard to reason about. This is why the scope blocks that introduce
local scope require the global keyword to declare the intent to modify
a global variable.
This question already has answers here:
In MATLAB, can I have a script and a function definition in the same file?
(7 answers)
Closed 6 years ago.
I write some program at Matlab. I do it in .m file. And it's 300+ strings of code now, so it became not very comfortable for reading. My idea is to use it like in C++: I want to create local functions at the end of this file and put pieces of code into them. It would be easy to read and it would consist of some logical parts.
But I faced the fact that local functions can be created only in body of other function! So I can't create this:
x = 1;
y = 2;
z = myLocalFnc(x,y);
function res = myLocalFnc (a,b)
res = a.*b;
end
This generate error:
Function definitions are not permitted in this context.
I can do it by including the whole code into one function:
function myBigFcn
x = 1;
y = 2;
z = myLocalFnc(x,y);
end
function res = myLocalFnc (a,b)
res = a.*b;
end
But now all the variables became local and it return to workspace nothing.
Modify input/output for this function any time I create some variable - I don't think I walk the right way... Here are described advantages and disadvantages of this method.
I know I can create function in additional .m file, save it and use in my script - OK, but a lot of them are single-operation, I don't want to create so much new files.
My question is ARE any other methods of code organizing?
If you really want your main thing to be a script (I don't recommend this), you can put all the other functions in separate .m files and call those from within the script.
The other option, as you've noted is to put the entire contents of your "main" part into a function at the top of your code. You can return all the necessary values via the output arguments or save them to a .mat file if you need access to them later.
As a side note, the ability to put local functions within a script (what you're trying to do) is present in R2016b which will be released later this Fall.
Update
If you want an easy way to convert your code to a function. You can easily save all variables to a struct at the end of your function automatically and just return this struct.
function output = my_script_that_is_now_a_function(inputs)
% Do stuff
% Now save all variables in a struct and return it
tmpfile = tempname;
save(tmpfile);
output = load(tmpfile);
delete(tmpfile);
end
One option, if you don't mind saving a file locally, is to restructure your code into multiple functions (all in the same file) and pass the necessary variables as output. You then have a short script which calls this function and creates the necessary variables.
For example, say your script looks like this
numPoints = 5;
a = randn(numPoints);
b = sin(a);
c = a + b;
You could restructure it to look like
function data = main()
data.numPoints = 5;
data.a = getA(data.numPoints);
data.b = getB(data.a);
data.c = getC(data.a, data.b);
function a = getA(numPoints)
a = randn(numPoints);
function b = getB(a)
b = sin(a);
function c = getC(a, b)
c = a + b;
and create a script file which looks like
data = main();
You then have a struct called data which contains all of your variables. If you really want them to be contained in separate variables (i.e. not in a struct) then there are a couple of ways to do it. One is to unpack them manually,
a = data.a;
b = data.b;
c = data.c;
clear data;
Another is to save the struct, and then reload it (this has the advantage of keeping a copy of the workspace that you used for this fun of the function, for later analysis).
save('workspace.mat', '-struct', 'data');
load('workspace.mat');
Why can't the factory function fromto return the local function iter as an iterator to the for loop?
function fromto(from,to)
return iter,to,from-1
end
local function iter(to,from)--parameter:invariant state, control variable
from = from + 1
if from <= to then
return from
else
return nil
end
end
for i in fromto(1,10) do
print(i)
end
As #YuHao says, your scheme can work. There are a few ways you could rearrange your code. Here's one:
local function fromto(from,to)
--parameter:invariant state, control variable
local function iter(to,from)
from = from + 1
if from <= to then
return from
else
return nil
end
end
return iter,to,from-1
end
for i in fromto(1,10) do
print(i)
end
Two things to understand: variable scope and functions are values.
Variables are either global or local. Local variables are lexically scoped. They are in scope from the statement following their declaration up to the end of the block. If a name is not the name of a local variable it becomes a global variable reference. On your line 2, iter is a global variable.
Functions are not declared, they are values created when a function definition expression is executed. (A function defintion statement is simply an alternate syntax for a function definition expression and assignment to a variable.) Also, functions don't have names. They are simply referenced by one or more variables. So, your function value does exist and get referenced by the iter variable until execution control passes through the lines that contain the function definition. In your code, that's the end of line 11.
The factory / iterator function is implemented correctly. The problem is, by using
local function iter(to,from)
--...
end
is equivalent to:
local iter = function(to,from)
--...
end
iter is a local variable that fromto has no access to. Remove local and it will run.
I am designing my own experimental scripting language for the purpose of embedding it in my bigger application.
Almost everything I wanted to do was programmed smoothly, but the "simple" act of storing variables in memory appeared to be the hardest part here. I don't know how to store them to allow all type checking, global variables and special flags on them. First look at a sample code:
a = 1
b = 2
someFunction()
print(a) --> This should read the global variable and print `1`
a = 3 --> Now `a` should become a local variable of this function
and the global `a` remain unchanged
x = 4 --> `x` should always be local of this function
end
I call the "locality" of variables their levels so variables in nested blocks have a higher level. In the above code, a and b are level 1 variables. Local variables of someFunction will have level 2. The first line of the function should read the global variable a (level 1) but the second line should create a variable again called a but with level 2 that shadows the global a from that point onwards. The third line should create the variable x with level 2. How to store and keep track of all these in memory?
What I tried so far:
Method 1: Storing maps of variable=>value in array of levels:
variables
{
level=1 //global variables
{
a => 1,
b => 2
},
level=2 //function variables
{
a => 3,
x => 4
}
}
But that will make variable look-up really slow since one has to search all the levels for a given variable.
Method 2: Storing the (variable, level) pairs as keys of a map:
variables
{
(a, 1) => 1, //global
(b, 1) => 2, //global
(a, 2) => 3, //function
(x, 2) => 3 //function
}
This has the same problem as before since we have to try the pair (variable, level) with all possible levels for a given variable.
What method should I use for optimal memory usage and fastest access time?
Additional notes:
I know about how variables are managed on stack and heap on other "real" languages, but I find it tricky to do this on an interpreted language. "This mustn't be how Lua and Python do that," I always think. Correct me if I'm wrong. I'm trying to store the variable in maps and internal C++ structures.
And finally, this is how I represent a variable. Do you think it's big and there can be more memory-efficient representations? (I've also tried to put the "Level" as a member here but it had the same problem as the other too.)
struct Member
{
uchar type; //0=num, 1=str, 2=function, 3=array, etc
uchar flags; //0x80 = read-only, 0x40 = write-only, etc
union {
long double value_num;
char* value_str;
int value_func;
//etc
};
};
An easy thing to do, similar to your array, is to maintain a stack of maps. Each map contains the bindings for that scope. To bind a variable, add it to the top map; to look up a variable, start at the top of the stack and stop when you reach a map that contains a binding for that variable. Search takes a little bit, but starting from the top/end you only have to search until you find it — in most cases, this search will not be very long.
You can also make the stack implicit by encapsulating this logic in an Environment class that has local bindings and an inherited environment used for resolving unknown variables. Need to go into a new scope? Create a new environment with the current environment as its base, use it, then discard it when the scope is finished. The root/global environment can just have a null inherited environment. This is what I would probably do.
Its worth noting that if, inside a function, you don't have access to any variables from the caller function, it lowers the number of levels you need to look at. For example:
variable a;
function one() {
variable b;
// in this function, we can see the global a, local b
two();
}
function two() {
// in this function, we can see the global a, local c
// we cannot see the local b of our caller
variable c;
while (true) {
variable d;
// here we can see local d, local c, global a
}
}
The idea being that function boundaries limit the visibility of variables, with the global scope being "special".
That being said, you can consider removing the specialness of global variables, but allowing the code to specify that they want access to non-local variables
variable a;
function one() {
global a; // or upvar #0 a;
variable b;
// in this function, we can see the global a, local b
two();
}
function two() {
// in this function, we can see the local c
// and the local b of our caller
// (since we specifically say we want access to "b" one level up)
upvar 1 b;
variable c;
}
It looks complicated at first, but it's really easy to understand once you get used to it (upvar is a construct from the Tcl programming language). What it allows you is access to variables in your caller's scope, but it avoids some of the costly lookup involved by requiring that you specify exactly where that variable comes from (with 1 being one level up the call stack, 2 being two levels up, and #0 being "special" in saying "the uppermost call stack, the global)