To apply a sequence of definitions to an expression in order to simplify it, calculate its value or get a numerical approximation of its value, call the expr.simplify(), expr.evaluate() or expr.N() function.
The Compute Engine supports lexical scoping.
A scope includes a symbol table, which is a collection of definitions for symbols and functions.
Scopes are arranged in a stack, with the current (top-most) scope available with
To locate the definition of an identifier, the symbol table associated with the current (top-most) scope is searched first. If no matching definition is found, the parent scope is searched, and so on until a definition is found.
To add a new scope to the context use
ce.pushScope(); ce.assign('x', 500); // "x" is defined in the new scope
To exit a scope use
This will invalidate any definition associated with the scope, and restore the symbol table from previous scopes that may have been shadowed by the current scope.
Name Binding is the process of associating an identifier (the name of a function or symbol) with a definition.
Name Binding should not be confused with value binding with is the process of associating a value to a symbol.
For symbols, the definition records contain information such as the domain of the symbol and its value. For functions, the definition record include the signature of the function (the domain of the argument it expects), and how to simplify or evaluate function expressions that have this function as their head.
Name binding is done during canonicalization. If name binding failed, the
isValid property of the expession is
To get a list of the errors in an expression use the
This is an advanced topic. You don’t need to know the details of how the evaluation loop works, unless you’re interested in extending the standard library and providing your own function definitions.
Each identifier (name of symbol or function) is bound to a definition within
a scope during canonicalization. This usually happens when calling
ce.parse(), but could also happen during
expr was not canonical.
When a function is evaluated, the following steps are followed:
If the expression is not canonical, it is put in canonical form
Each argument of the function are evaluated, left to right.
An argument can be held, in which case it is not evaluated. Held arguments can be useful when you need to pass a symbolic expression to a function. If it wasn’t held, the result of evaluating the expression would be used, not the symbolic expression.
A function definition can indicate that one or more of its arguments should be held.
Alternatively, using the
Holdfunction will prevent its argument from being evaluated. Conversely, the
ReleaseHoldfunction will force an evaluation.
If an argument is a
["Sequence"]expression, treat each argument of the sequence expression as if it was an argument of the function. If the sequence is empty, ignore the argument.
If the function is associative, flatten its arguments as necessary. \[ f(f(a, b), c) \to f(a, b, c) \]
Apply the function to the arguments
Return the canonical form of the result
The same evaluation loop is used for