Optionalaritynumber of arguments the term is waiting for (if known)
Optionalcontextoptional context for the term. Is set by the parser with addContext: true
Optionalnotea brief description what the term does
Optionalpropsthe properties of the term, typically inferred from its behavior. This is used internally when declaring Native / Alias terms.
OptionalsizeAn estimated number of nodes in the expression tree. Used to prevent runaway computations.
Protected_ProtectedWhether the expression needs to be parenthesized when printed in terse mode. (see format)
whether this is the first term in a sequence
Protected_ProtectedInternal method for fold(), which performs the actual folding. Should be implemented in subclasses having any internal structure.
Protected_ProtectedApply a traverse callback to the subterms of the expression, without changing the expression itself.
Protected_Protected_ProtectedWhether the expression can be printed without a space when followed by arg.
ExperimentalAdd metadata based on user-supplied values and/or the properties of the term itself.
Typically applied to named terms shortly after instantiation.
Experimental. Name and meaning may change in the future.
Optionalarity?: numbernumber of arguments the term is waiting for (if known)
Optionalcanonize?: booleanwhether to try to infer the properties
Optionalfancy?: stringhow to display in html mode, e.g. φ instead of 'f'
Optionalmax?: numbermaximum number of steps for inference, if canonize is true
OptionalmaxArgs?: numbermaximum number of arguments for inference, if canonize is true
Optionalnote?: stringa brief description what the term does
Returns true if predicate() is true for any subterm of the expression, false otherwise.
Returns a string representation of the expression tree, with indentation to show structure.
Applications are flattened to avoid excessive nesting.
Variables include ids to distinguish different instances of the same variable name.
May be useful for debugging.
Recursively compare two expressions and return a string describing the first point of difference. Returns null if expressions are identical.
Aliases are expanded.
Bound variables in lambda terms are renamed consistently.
However, no reductions are attempted.
Members of the FreeVar class are considered different
even if they have the same name, unless they are the same object.
To somewhat alleviate confusion, the output will include
the internal id of the variable in square brackets.
Do not rely on the exact format of the output as it may change in the future.
If true, the order of expressions is reversed in the output.
True is the expressions are identical, false otherwise. Aliases are expanded. Bound variables in lambda terms are renamed consistently. However, no reductions are attempted.
E.g. a->b->a == x->y->x is true, but a->b->a == K is false.
Final. Current implementation is a frontend to diff.
Replace all aliases in the expression with their definitions, recursively.
SealedAssert expression equality. Can be used in tests.
this is the expected value and the argument is the actual one.
Mnemonic: the expected value is always a combinator, the actual one may be anything.
In case of failure, an error is thrown with a message describing the first point of difference
and expected and actual properties like in AssertionError.
AssertionError is not used directly because browsers don't recognize it.
ExperimentalFold the expression into a single value by recursively applying combine() to its subterms. Nodes are traversed in leftmost-outermost order, i.e. the same order as reduction steps are taken.
null or undefined return value from combine() means "keep current value and descend further".
SKI.control provides primitives to control the folding flow:
This method is experimental and may change in the future.
ExperimentalFold an application tree bottom to top. For each subtree, the function is given the term in the root position and a list of the results of folding its arguments.
E.g. fold('x y (z t)', f) results in f(x, [f(y, []), f(z, [f(t, [])])])
SealedStringify the expression with fancy formatting options.
Said options mostly include wrappers around various constructs in form of ['(', ')'],
as well as terse and html flags that fill in appropriate defaults.
Format without options is equivalent to toString() and can be parsed back.
Optionaloptions: FormatOptions = {}formatting options
Optionalaround?: [string, string]Optionalbrackets?: [string, string]Optionalhtml?: booleanOptionalinventory?: Record<string, Named>Optionallambda?: [string, string, string]Optionalredex?: [string, string]Optionalspace?: stringOptionalterse?: booleanOptionalvar?: [string, string]Protected AbstractformatProtectedInternal method for format(), which performs the actual formatting.
SealedTry to empirically find an equivalent lambda term for the expression, returning also the term's arity and some other properties.
This is used internally when declaring a Native / Alias term,
unless {canonize: false} is used.
As of current it only recognizes terms that have a normal form,
perhaps after adding some variables. This may change in the future.
Use toLambda() if you want to get a lambda term in any case.
Apply term reduction rules, if any, to the given argument. A returned value of null means no reduction is possible. A returned value of Expr means the reduction is complete and the application of this and arg can be replaced with the result. A returned value of a function means that further arguments are needed, and can be cached for when they arrive.
This method is between apply() which merely glues terms together, and step() which reduces the whole expression.
foo.invoke(bar) is what happens inside foo.apply(bar).step() before reduction of either foo or bar is attempted.
The name 'invoke' was chosen to avoid confusion with either 'apply' or 'reduce'.
SealedIteratively apply step to the expression until it's irreducible, or until the provided limits are reached.
Returns { expr: Expr, steps: number, final: boolean }.
If { throw: true } is given and no irreducible form was reached within the limits, an error is thrown.
Optionalopt: Expr | RunOptions = {}iterate one step of a calculation.
Replace all instances of search in the expression with replace and return the resulting expression,
or null if no changes could be made.
Lambda terms and applications will never match if used as plug as they are impossible to compare without extensive computations.
Typically used on variables but can also be applied to other terms, e.g. aliases. See also Expr.traverse() for more flexible replacement of subterms.
Experimental SealedConvert the expression to a JSON-serializable format. Sadly the format is not yet finalized and may change in the future.
SealedReturns a series of lambda terms equivalent to the given expression, up to the provided computation steps limit.
Unlike infer(), this method will always return something,
even if the expression has no normal form.
See also Expr.walk() and Expr.toSKI().
SealedRewrite the expression into S, K, and I combinators step by step. Returns an iterator yielding the intermediate expressions, along with the number of steps taken to reach them.
See also Expr.walk() and Expr.toLambda().
Optionaloptions: { max?: number; maxArgs?: number } = {}SealedReturns string representation of the expression. Same as format() without options.
Use formatImpl() to override in subclasses.
SealedTraverse the expression tree, applying change() to each node. If change() returns an Expr, the node is replaced with that value. A null/undefined value is interpreted as "descend further if applicable, or leave the node unchanged".
Returned values may be decorated:
SKI.control.prune will suppress further descending even if nothing was returned
SKI.control.stop will terminate further changes.
SKI.control.redo will apply the callback to the returned subtree, recursively.
Note that if redo was applied at least once to a subtree, a null return from the same subtree
will be replaced by the last non-null value returned.
The traversal order is leftmost-outermost, unless options.order = 'leftmost-innermost' is specified.
Short aliases 'LO' and 'LI' (case-sensitive) are also accepted.
Returns null if no changes were made, or the new expression otherwise.
Optionaloptions: TraverseOptions | TraverseCallbackOptionalchange: TraverseCallbackExpand an expression into a list of terms that give the initial expression when applied from left to right: ((a, b), (c, d)) => [a, b, (c, d)]
This can be thought of as an opposite of apply: fun.apply(...arg).unroll() is exactly [fun, ...args] (even if ...arg is in fact empty).
Returns an iterator of reduction steps of the expression, up to the provided limits. Each step is an object of { expr, steps, final }, same as in run.
Mnemonics: like run but slower.
This method is final. Do not override, override step instead.
A lambda abstraction.
Takes an arg: FreeVar and an impl: Expr. Upon evaluation, all occurrences of
argwithinimplwill be replaced by the given term.Note that 'arg' will be replaced by a localized placeholder, so the original variable can be used elsewhere without interference.