Global Variables and Scope of Variables

GEL is a dynamically scoped language. We will explain what this means below. That is, normal variables and functions are dynamically scoped. The exception are parameter variables, which are always global.

Like most programming languages, GEL has different types of variables. Normally when a variable is defined in a function, it is visible from that function and from all functions that are called (all higher contexts). For example, suppose a function f defines a variable a and then calls function g. Then function g can reference a. But once f returns, the variable a goes out of scope. For example, the following code will print out 5. The function g cannot be called on the top level (outside f as a will not be defined).

function f() = (a:=5; g());
function g() = print(a);
f();

If you define a variable inside a function it will override any variables defined in calling functions. For example, we modify the above code and write:

function f() = (a:=5; g());
function g() = print(a);
a:=10;
f();

This code will still print out 5. But if you call g outside of f then you will get a printout of 10. Note that setting a to 5 inside f does not change the value of a at the top (global) level, so if you now check the value of a it will still be 10.

Function arguments are exactly like variables defined inside the function, except that they are initialized with the value that was passed to the function. Other than this point, they are treated just like all other variables defined inside the function.

Functions are treated exactly like variables. Hence you can locally redefine functions. Normally (on the top level) you cannot redefine protected variables and functions. But locally you can do this. Consider the following session:

genius> function f(x) = sin(x)^2
= (`(x)=(sin(x)^2))
genius> function f(x) = sin(x)^2
= (`(x)=(sin(x)^2))
genius> function g(x) = ((function sin(x)=x^10);f(x))
= (`(x)=((sin:=(`(x)=(x^10)));f(x)))
genius> g(10)
= 1e20

Functions and variables defined at the top level are considered global. They are visible from anywhere. As we said the following function f will not change the value of a to 5.

a=6;
function f() = (a:=5);
f();

Sometimes, however, it is necessary to set a global variable from inside a function. When this behavior is needed, use the set function. Passing a string or a quoted identifier to this function sets the variable globally (on the top level). For example, to set a to the value 3 you could call:

set(`a,3)

or:

set("a",3)

The set function always sets the toplevel global. There is no way to set a local variable in some function from a subroutine. If this is required, must use passing by reference.

See also the SetElement and SetVElement functions.

So to recap in a more technical language: Genius operates with different numbered contexts. The top level is the context 0 (zero). Whenever a function is entered, the context is raised, and when the function returns the context is lowered. A function or a variable is always visible from all higher numbered contexts. When a variable was defined in a lower numbered context, then setting this variable has the effect of creating a new local variable in the current context number and this variable will now be visible from all higher numbered contexts.

There are also true local variables that are not seen from anywhere but the current context. Also when returning functions by value it may reference variables not visible from higher context and this may be a problem. See the sections True Local Variables and Returning Functions.