-
-
Notifications
You must be signed in to change notification settings - Fork 0
env Variable
This is a class that defines instances of logical variables. It is one of the major parts of the unification process and logical solvers.
Variable is based on Unifier and provides a useful helpers to deal with environments (see Env for more details).
It is defined in env and can be accessed like that:
import {Env, Variable} from 'deep6/env.js';Usually a helper factory function is used to create instances of Variable: variable().
Let's redo the example from Env:
const env = new Env(),
a = new Variable('a'), // can be accessed as 'a'
b = new Variable(), // anonymous
c = new Variable(); // anonymous
a.isBound(env); // false
b.isBound(env); // false
c.isBound(env); // false
// push a generation frame
env.push();
env.bindVal(a.name, 1);
a.isBound(env); // true
b.isBound(env); // false
c.isBound(env); // false
a.get(env); // 1
// push a generation frame
env.push();
a.isBound(env); // true
b.isBound(env); // false
c.isBound(env); // false
env.bindVar(c.name, b.name);
a.isBound(env); // true
b.isBound(env); // false
c.isBound(env); // false
env.isAlias(a.name, b.name); // false
env.isAlias(b.name, c.name); // true
env.isAlias(c.name, a.name); // false
a.isAlias(b, env); // false
b.isAlias(c, env); // true
c.isAlias(a, env); // false
env.bindVal(b.name, 2);
a.isBound(env); // true
b.isBound(env); // true
c.isBound(env); // true
a.get(env); // 1
b.get(env); // 2
c.get(env); // 2
// drop a generation frame
env.pop();
a.isBound(env); // true
b.isBound(env); // false
c.isBound(env); // falseAll attributes (bound, aliased) are recorded in an environment, not in a variable itself. It allows using the same variable object with different environments at the same time.
const x = new Variable(),
env1 = new Env(),
env2 = new Env();
x.isBound(env1); // false
x.isBound(env2); // false
env1.bindVal(x.name, 1);
x.isBound(env1); // true
x.isBound(env2); // false
x.get(env1); // 1
env2.bindVal(x.name, 'two');
x.isBound(env1); // true
x.isBound(env2); // true
x.get(env1); // 1
x.get(env2); // 'two'This class defines objects with the following properties:
-
name— a string or a symbol that is unique for this logical variable.- It is possible to create several instances of
Variablewith the same name. In this case, logically it will be the same logical variable.
- It is possible to create several instances of
The class defines the following methods:
The constructor creates a logical variable with a given name. It takes the following arguments:
-
name— an optional string or a symbol value that is unique for this logical variable. If it is not supplied or falsy (an empty string), a unique symbol value is generated.- This value is stored as
nameproperty so it can be accessed later.
- This value is stored as
It is a convenience method that corresponds to env.isBound(name). The method returns a truthy value if a variable is already bound to a value. Computationally it is very cheap (O(1)). It takes the following arguments:
-
env— an environment object (see Env).
The current implementation:
isBound(env) {
return env.isBound(this.name);
}It is a convenience method that corresponds to env.isAlias(name1, name2). The method returns a truthy value if variables are already aliased to each other. Computationally it is very cheap (O(1)). It takes the following arguments:
-
name— a variable name as a string or a symbol or aVariableobject. -
env— an environment object (see Env).
The procedure is completely symmetric:
const x = new Variable(),
y = new Variable(),
env = new Env();
env.bindVar(x.name, y.name);
x.isAlias(y, env); // true
y.isAlias(x, env); // trueThe current implementation:
isAlias(name, env) {
return env.isAlias(name instanceof Variable ? name.name : name, this.name);
}It is a convenience method that corresponds to env.get(name). The method returns a value bound to a variable. Computationally it is very cheap (O(1)). It takes the following arguments:
-
env— an environment object (see Env).
No checks are done that the variable is bound. Correctness checks should be done externally before calling the method. If a variable is not bound in the environment, get() will return undefined.
Example:
const a = new Variable();
const value = 1; // some arbitrary value
env.bindVal(a.name, value);
a.get(env) === value; // trueThe current implementation:
get(env) {
return env.get(this.name);
}This method is required by Unifier and used internally.
The unification algorithm for a variable:
- If the variable is bound, we unify its value with
val, by pushing them to thels-rspair. - If
valis any, it is unified unconditionally. - If
valis another variable:- If it is bound, we bind the variable to that value.
- Otherwise, we bind these two variables making them aliased.
- Bind the variable to
val.
In all cases, the actual unification is delegated through the ls-rs pair, and the method returns true.