A domain is most abstractly defined by a constraint, a function which determines, for a given value, whether or not it is part of the domain. A constraint which always returns false will define an empty domain; a constraint which always returns true will define the infinite domain of all possible values.
The domain of a function is the set of values the function will accept as input (precondition.) The range of a function is the set of values the function might output (postcondition.) They are both defined by domain constraints.
A variable is a (named) storage space. It contains one representation of a value at a time. A variable has a domain that defines which values may be assigned to the variable.
A value may have a type associated with it. A type is an assertion that the value is a member of a particular (named) domain. Other domain constraints may use this as a starting point (assumption) from which appropriate tests may be devised to decide the membership of a value in a particular domain. Type, if included at all, is part of the value itself.
Deterministic functions consistently return the same value when given the same parameters. Using non-deterministic functions in a domain constraint definition may lead to errors.
[TODO: constants, side-effects, procedures, symbols, L-values, R-values, passing functions as parameters -- functions as values rather than symbols, unnamed functions, l-values with parameters, namespaces, overloading, overriding, most-specific type, function priority, ...]