Kenpali Core Specification
The Core functions must be available to any Kenpali program. Reference implementations for some of them in terms of the others are provided by core.kpc, enabling a complete implementation with fewer platform functions.
Arithmetic
add
Returns the sum of its arguments
Parameters:
*numbers(Array of Number): The numbers to add up.
Returns:
- (Number): The sum.
sum
Returns the sum of the values in the specified sequence.
Parameters:
numbers(Sequence of Number): The numbers to add up.
Returns:
- (Number): The sum.
sub
Returns its first argument minus its second argument.
Parameters:
a(Number): The amount to subtract from.b(Number): The amount to take away.
Returns:
- (Number): The difference.
negative
Returns its argument with the sign flipped.
Parameters:
n(Number): The value to negate.
Returns:
- (Number): The negated value.
absolute
Returns its argument with the sign set to positive.
Parameters:
n(Number): The value to make positive.
Returns:
- (Number): The absolute value.
up
Returns its argument plus one.
Parameters:
n(Number): The value to increase.
Returns:
- (Number): The incremented value.
down
Returns its argument minus one.
Parameters:
n(Number): The value to decrease.
Returns:
- (Number): The decremented value.
mul
Returns the product of its arguments.
Parameters:
*numbers(Array of Number): The values to multiply.
Returns:
- (Number): The product.
div
Returns its first argument divided by its second argument.
Parameters:
a(Number): The dividend.b(Number): The divisor.
Returns:
- (Number): The quotient.
oneOver
Returns the reciprocal of its argument.
Parameters:
x(Number): The value to invert.
Returns:
- (Number): The reciprocal.
quotientBy
Returns the integer quotient of its first argument divided by its second argument.
Parameters:
a(Number): The dividend.b(Number): The divisor.
Returns:
- (Number): The integer quotient.
remainderBy
Returns the remainder of its first argument divided by its second argument.
A non-zero remainder always has the same sign as the divisor.
Parameters:
a(Number): The dividend.b(Number): The divisor.
Returns:
- (Number): The remainder.
isDivisibleBy
Returns whether its first argument is divisible by its second argument.
Parameters:
a(Number): The dividend.b(Number): The divisor.
Returns:
- (Boolean): Whether
adivided bybis an integer.
Strings
toCodePoints
Returns an array of Unicode code points representing the characters in the given string.
Parameters:
string(String): The text to convert.
Returns:
- (Array of Number): The code points.
fromCodePoints
Returns a string created from the given array of Unicode code points.
Parameters:
codePoints(Array of Number): The code points to convert.
Returns:
- (String): The resulting text.
join
Returns a string created by joining the given values with a separator.
Parameters:
strings(Array or Stream of String): The values to join.on:(String, default""): The separator to insert between values.
Returns:
- (String): The joined string.
joinLines
Returns a string created by joining the given values with newlines.
Parameters:
strings(Array or Stream of String): The values to join.
Returns:
- (String): The joined string.
split
Returns an array of substrings by splitting the given string at occurrences of a separator.
Parameters:
string(String): The text to split.on:(String): The separator to split on.
Returns:
- (Array of String): The split substrings.
splitLines
Returns an array of the newline-separated lines in the specified string.
Parameters:
string(String): The text to split.
Returns:
- (Array of String): The lines.
Comparison
Comparison Rules
Kenpali can perform equality and ordering comparisons on various types.
All comparisons are strict about types: testing values of different types for equality always returns false, while using ordering comparisons on different types always throws a wrongArgumentType error.
Any two values can be tested for equality. To be considered equal, the values must have the same type, and:
- If both are booleans, they must both be true or both be false.
- If both are numbers, they must have the same numerical value.
- If both are strings, they must have the same sequence of Unicode code points.
- If both are arrays, they must have the same length, and corresponding elements must be equal according to the
eqfunction. - If both are objects, they must have the same property names, and corresponding property values must be equal according to the
eqfunction. The order in which the properties are written does not affect equality. - Otherwise, they must be aliases referring to the same data in memory.
Ordering comparisons work on booleans, numbers, strings, and arrays, as follows:
- For booleans,
falseis less thantrue. - Numbers are compared by numerical value.
- Strings are compared lexicographically by their Unicode code points.
- Arrays are compared lexicographically by their elements.
eq
Returns whether its arguments have equal values, according to the Comparison Rules.
Parameters:
a(Any): The first value.b(Any): The second value.
Returns:
- (Boolean): Whether the values are equal.
lt
Returns whether its first argument is less than its second argument, according to the Comparison Rules.
Parameters:
a(Number, String, Boolean, or Array): The first value.b(Number, String, Boolean, or Array): The second value.
Returns:
- (Boolean): Whether
ais less thanb.
le
Returns whether its first argument is less than or equal to its second argument, according to the Comparison Rules.
Parameters:
a(Number, String, Boolean, or Array): The first value.b(Number, String, Boolean, or Array): The second value.
Returns:
- (Boolean): Whether
ais less than or equal tob.
gt
Returns whether its first argument is greater than its second argument, according to the Comparison Rules.
Parameters:
a(Number, String, Boolean, or Array): The first value.b(Number, String, Boolean, or Array): The second value.
Returns:
- (Boolean): Whether
ais greater thanb.
ge
Returns whether its first argument is greater than or equal to its second argument, according to the Comparison Rules.
Parameters:
a(Number, String, Boolean, or Array): The first value.b(Number, String, Boolean, or Array): The second value.
Returns:
- (Boolean): Whether
ais greater than or equal tob.
isBetween
Returns whether its first argument is between the specified lower and upper bounds, according to the Comparison Rules.
Both bounds are inclusive.
Parameters:
n(Number, String, Boolean, or Array): The value to test.lower(Number, String, Boolean, or Array): The lower bound.upper(Number, String, Boolean, or Array): The upper bound.
Returns:
- (Boolean): Whether
nis betweenlowerandupper.
least
Returns the least element in the specified sequence, i.e. the element that is less than or equal to all other elements, according to the Comparison Rules.
Parameters:
sequence(Sequence): The values to find the least element of.
Returns:
- (Number, String, Boolean, or Array): The least element.
greatest
Returns the greatest element in the specified sequence, i.e. the element that is greater than or equal to all other elements, according to the Comparison Rules.
Parameters:
sequence(Sequence): The values to find the greatest element of.
Returns:
- (Number, String, Boolean, or Array): The greatest element.
Logic
and
Returns whether all given conditions evaluate to true. If any condition evaluates to false, the remaining conditions are not evaluated.
Parameters:
first(Boolean): The first condition.*rest(Array of Function returning Boolean): The remaining conditions.
Returns:
- (Boolean): Whether all conditions are
true.
or
Returns whether at least one of the given conditions evaluates to true. If any condition evaluates to true, the remaining conditions are not evaluated.
Parameters:
first(Boolean): The first condition.*rest(Array of Function returning Boolean): The remaining conditions.
Returns:
- (Boolean): Whether any condition is
true.
not
Returns the logical negation of its argument.
Parameters:
x(Boolean): The value to negate.
Returns:
- (Boolean): The negated value.
Types and Type Conversion
Type Constants
A class value is defined for each of the basic types.
There are also protocol constants for the following protocols:
Sequencecovers collections with a definite order: strings, arrays, and streams.Instancecovers all values except null, booleans, numbers, strings, arrays, objects, and functions.Typecovers values that represent Kenpali types: classes and protocols.Anycovers all values.
classOf
Returns the Kenpali class of its argument.
Parameters:
value(Any): The value whose class to get.
Returns:
- (Class): The Kenpali class.
isNull
Returns whether its argument is null.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueisnull.
isBoolean
Returns whether its argument is a boolean.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a boolean.
isNumber
Returns whether its argument is a number.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a number.
toNumber
Returns the numeric value of its argument.
Parameters:
value(String or Number): The value to convert.
Returns:
- (Number): The numeric value.
Throws:
notNumeric: Ifvalueis a string that cannot be parsed as a number.
isString
Returns whether its argument is a string.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a string.
display
Returns a string representation of its argument, suitable for reporting the result of a computation. This is generally not suitable for user-friendly text, which should use formatting logic specific to the type being displayed.
Calling display on a stream reports already evaluated elements but never forces further evaluation.
Parameters:
value(Any): The value to convert.
Returns:
- (String): The string value.
isArray
Returns whether its argument is an array.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis an array.
toArray
Collects the elements of the specified sequence into an array.
Parameters:
value(Sequence): The value to convert.
Returns:
- (Array): The array of elements.
isStream
Returns whether its argument is a stream.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a stream.
toStream
Returns a stream that iterates over the elements of the specified sequence.
If the argument is already a stream, the same stream is returned, rather than a wrapper, i.e. x | toStream | eq(x) is true if x is a stream.
Parameters:
value(Sequence): The value to convert.
Returns:
- (Stream): The stream of elements.
isObject
Returns whether its argument is an object.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis an object.
toObject
Converts the specified value into an object.
If the value is an array or stream, its elements are treated as key-value pairs. Any duplicate keys are assigned the value from the last pair with that key in the sequence.
If the value is an instance, an object containing its class name and properties is returned.
Parameters:
value(Array or Instance): The value to convert. If an array or stream, it must contain tuples like [string, any].
Returns:
- (Object): An object constructed from
value.
isFunction
Returns whether its argument is a function.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a function.
toFunction
Converts the specified value to a function:
- If the argument is already a function, the same function is returned.
- Otherwise, a constant function that returns the specified value is returned.
Parameters:
value(Any): The value to convert.
Returns:
- (Function): The function.
isError
Returns whether its argument is an error.
Note that merely calling this function doesn’t catch a thrown error: if x throws, x | isError propagates the error rather than returning true. The error must be explicitly caught first, i.e. try($ x, onError: itself) | isError.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis an error.
isClass
Returns whether its argument is a class.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a class.
isProtocol
Returns whether its argument is a protocol.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a protocol.
isSequence
Returns whether its argument is a sequence—a string, array, or stream.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a sequence.
isType
Returns whether its argument is a type—a class or protocol.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis a type.
isInstance
Returns whether its argument is an instance—a value with an object-like structure belonging to a specific class. All types other than functions and the JSON types are considered instances.
Parameters:
value(Any): The value to check.
Returns:
- (Boolean): Whether
valueis an instance.
Control Flow
if
Evaluates and returns the result of one of two functions based on a condition.
Parameters:
condition(Boolean): The condition to check.then:(Function): The function to call ifconditionistrue.else:(Function): The function to call ifconditionisfalse.
Returns:
- (Any): The result of the evaluated function.
butIf
Substitutes a different value if a condition is true.
Parameters:
value(Any): The original value.condition(Boolean or Function): The condition to check. If this is a function, it is called withvalueas its argument to get the condition’s truth value.ifTrue(Function): A function that returns the value to substitue ifconditionis true. This is called withvalueas its argument.
Returns:
- (Any):
valueifconditionis false, the result ofifTrueotherwise.
ifs
Evaluates a list of conditions and returns the result of the first matching case.
Parameters:
conditions(Array of tuple like [Function, Function]): A list of condition-result pairs. Each condition function is called with no arguments, and if it returnstrue, the corresponding result function is called with no arguments and its result is returned.else:(Function): The function to call if no conditions match.
Returns:
- (Any): The result of the first matching case, or the
elsefunction if no conditions match.
switch
Evaluates a list of conditions on an input value and returns the result of the first matching case.
Parameters:
value(Any): The value to pass to conditions and results.conditions(Array of tuple like [Function, Function]): A list of condition-result pairs. Each condition function is called withvalue, and if it returnstrue, the corresponding result function is called withvalueand its result is returned.else:(Function): The function to call if no conditions match.
Returns:
- (Any): The result of the first matching case, or the
elsefunction if no conditions match.
Stream Builders
These functions build up new streams from scalar inputs.
Stream
A stream is a lazily computed sequence of values. It is inspired by similar concepts in other languages (often called generators or iterators), but the key difference is that streams remember the values they have already computed, so they can be iterated over multiple times. Of course, this should be implemented in such a way that values that are no longer reachable are freed—for example, by storing them in a linked list.
In general, streams must not compute anything more than is absolutely necessary to produce the values that have been requested. They must also take care to avoid stack overflow—iterating over a stream must interleave calls and returns in a way that avoids building up a large call stack.
newStream
Explicitly creates a stream with the specified head value and tail stream.
Parameters:
value:(Function): A function that returns the first value in the stream.next:(Function): A function that returns the remaining values in the stream, as a stream. This normally makes a recursive call to the containing function, allowing the stream to continue indefinitely.
Returns:
- (Stream): The new stream.
emptyStream
Creates a stream with no elements. Together with newStream, this allows explicitly creating finite streams.
Returns:
- (Stream): An empty stream.
Stream/isEmpty
Returns whether the specified stream is empty.
Returns:
- (Boolean): True if the stream is empty.
Stream/value
Returns the first element of the specified stream.
This property is absent if the stream is empty.
Returns:
- (Any): The first element.
Stream/next
Returns the rest of the specified stream.
This property is absent if the stream is empty.
Returns:
- (Stream): The rest of the stream.
build
Generates a stream by repeatedly applying a function to a start value.
Parameters:
start(Any): The start value.next(Function): A function that computes the next state from the current state.
Returns:
- (Stream): A stream containing
startand all values produced by thenextfunction.
As a well-behaved stream, the result of build doesn’t invoke next any more than is necessary to produce the values that have been requested.
As a well-behaved stream, the result of build can be iterated over thousands of times without overflowing the stack.
to
Generates a stream of numbers covering a range.
This is often useful for situations where other languages would use for loops.
Parameters:
start(Number): The number to start counting from. This is always the first element of the stream.end(Number): The number to stop at or before.by:(Number, default1): The number to count by. Each element of the stream will bebymore than the previous one. Ifbyis negative, the stream will count down. If the sign ofbyis opposite the sign ofend - start(i.e. counting the “wrong way”), the resulting stream is empty.
Returns:
- (Stream): A stream of numbers ranging from
starttoend, incrementing byby.
toSize
Generates a stream of incrementing numbers with a given size.
Parameters:
start(Number): The number to start counting from.size(Number): The number of elements to include in the stream.
Returns:
- (Stream): A stream of numbers counting up from
start, withsizeelements in total.
repeat
Creates a stream that repeats the same value forever.
Parameters:
value(Any): The value to repeat.
Returns:
- (Stream): An infinite stream all of whose elements are
value.
Stream Collapsers
These functions exhaust an input stream to produce a scalar output or side effect. They loop forever if given an infinite stream.
last
Returns the last element of the specified sequence. Equivalent to indexing with -1.
Parameters:
sequence(Sequence): The sequence to get the last element of.
Returns:
- (Any): The last element.
length
Returns the number of elements in the specified sequence.
For strings, this is the number of characters.
Parameters:
sequence(Sequence): The sequence to find the length of.
Returns:
- (Number): The length.
keepLast
Retains only the last n elements of the input.
Parameters:
sequence(Sequence): The sequence to take values from.n(Number): The number of elements to keep.
Returns:
- (Array or String): An array of at most
nelements, or a string containing the lastncharacters ifsequenceis a string.
dropLast
Drops the last n elements of the input.
Parameters:
sequence(Sequence): The sequence to drop values from.n(Number, default:1): The number of elements to drop.
Returns:
- (Array or String): An array with the last
nelements dropped, or a string with the lastncharacters dropped ifsequenceis a string.
count
Returns the number of elements in the sequence matching the specified condition.
Parameters:
sequence(Sequence): The sequence to count from.condition(Function): A function that returnstruefor elements to count.
Returns:
- (Number): The number of elements for which
conditionreturnstrue.
forAll
Tests whether the specified condition is true for all elements in the sequence.
Parameters:
sequence(Sequence): The sequence to test.condition(Function): A function that returnstruefor acceptable elements.
Returns:
- (Boolean): Whether all elements match the condition.
forSome
Tests whether the specified condition is true for at least one element in the sequence.
Parameters:
sequence(Sequence): The sequence to test.condition(Function): A function that returnstruefor acceptable elements.
Returns:
- (Boolean): Whether any elements match the condition.
reverse
Returns an array containing all the elements of the specified sequence in reverse order.
Parameters:
sequence(Sequence): The sequence to reverse.
Returns:
- (Array): The reversed array.
sort
Returns an array with the same elements as the specified sequence, but in ascending order.
If by is null, the elements are sorted in their natural order, following the Comparison Rules.
Otherwise, by is called on each element to obtain a sort key, and the elements are sorted by that sort key, again following the Comparison Rules. The sort is stable: two elements with equal sort keys will appear in the same relative order in the sorted array as they were in the original sequence.
Parameters:
sequence(Sequence): The sequence to sort.by:(Function or Null, defaultnull): A function to produce a sort key from each element, ornullto sort the elements in their natural order.
Returns:
- (Array): The sorted array.
group
Groups a sequence of pairs by their first element.
Parameters:
pairs(Sequence): A sequence of pairs whose first element is the grouping key.onGroup:(Function, default(x) => x): A function to call on each group after assembling it.
Returns:
- (Array): A sequence of pairs whose first element is the grouping key, and whose second element is the result of calling
onGroupon an array of the second elements of the input pairs with that grouping key.
groupBy
Groups a sequence by a key function.
Parameters:
sequence(Sequence): The sequence to group.by(Function): A function that returns a grouping key for a given value.onGroup:(Function, default(x) => x): A function to call on each group after assembling it.
Returns:
- (Array): A sequence of pairs whose first element is the grouping key, and whose second element is the result of calling
onGroupon an array of the elements with that grouping key.
forEach
Applies a function to each element in a sequence for its side effects.
Parameters:
sequence(Sequence): The sequence of values to iterate over.action(Function): The function to apply to each element.
Returns:
- (Array): The input sequence as an array.
Stream Accessors
These functions calculate a scalar value from a stream, but only access a finite number of elements to do so. Therefore, they are safe to call even on infinite streams.
isEmpty
Tests whether the specified sequence has no elements.
Parameters:
sequence(Sequence): The sequence to check for emptiness.
Returns:
- (Boolean): Whether the sequence is empty.
first
Returns the first element of the specified sequence. Equivalent to indexing with 1.
Parameters:
sequence(Sequence): The sequence to get the first element of.
Returns:
- (Any): The first element.
Stream Rebuilders
These functions create new streams that depend on existing ones, preserving stream laziness.
transform
Creates a stream from applying a function to each element in an input sequence.
Parameters:
sequence(Sequence): The sequence of values to transform.f(Function): The function to apply to each element.
Returns:
- (Stream): A stream of transformed values.
running
Maintains state while processing a sequence, producing a stream of intermediate states.
Parameters:
sequence(Sequence): The sequence of values to process.start:(Any): The initial state.next:(Function): A function that computes the next state from the current element and state. The state is passed as a named argumentstate:.
Returns:
- (Stream): A stream containing
startand all values produced by thenextfunction.
withIndex
Tags each element of the input sequence with its index.
Parameters:
sequence(Sequence): The sequence to add indices to.
Returns:
- (Stream): A stream of pairs, where the first element is the index and the second element is the element from the input sequence.
keepFirst
Retains only the first n elements of the input.
Parameters:
sequence(Sequence): The sequence to take values from.n(Number): The number of elements to keep.
Returns:
- (Stream or String): A stream of at most
nelements, or a string containing the firstncharacters ifsequenceis a string.
dropFirst
Skips the first n elements of the input.
Parameters:
sequence(Sequence): The sequence to skip values from.n(Number, default:1): The number of elements to drop.
Returns:
- (Stream or String): A stream with the first
nelements skipped, or a string with the firstncharacters skipped ifsequenceis a string.
slice
Extracts a sub-sequence of the specified sequence.
Parameters:
sequence(Sequence): The sequence to take values from.from:(Number): The index of the first element to take.to:(Number): The index of the last element to take.
Returns:
- (Stream or String): A stream containing only the elements from index
fromto indexto, or a string with the characters at those indices ifsequenceis a string.
while
Creates a stream of elements from the input sequence while a condition holds.
Parameters:
sequence(Sequence): The sequence to process.condition(Function returning Boolean): A function that returnsfalsewhen the stream should stop.
Returns:
- (Stream): A stream containing elements for which
conditionreturnstrue, stopping at the firstfalse.
continueIf
Creates a stream of elements from the input sequence, continuing to the next element if a condition holds. The resulting stream has one extra element compared to while—the first element that doesn’t satisfy the condition—which makes some stopping conditions easier to express.
Parameters:
sequence(Sequence): The sequence to process.condition(Function returning Boolean): A function that returnsfalsewhen the stream should stop.
Returns:
- (Stream): A stream containing the first element for which the condition returns
false, and all elements before it.
thenRepeat
Adds endless copies of a constant value to the end of the sequence.
This is useful if subsequent steps need to continue past the end of the stream.
Parameters:
sequence(Sequence): The initial sequence.value(Any): The value to repeat aftersequenceis exhausted.
sliding
Returns a stream containing arrays of adjacent elements in the input sequence.
Parameters:
sequence(Sequence): The input sequence.size(Number): The number of adjacent elements in each output array.
Returns:
- (Stream): A stream containing arrays with
sizeconsecutive elements each. The first array starts with the first element of the input sequence, the second array with the second element, and so on, with the last array ending on the last element of the input sequence.
where
Filters a sequence, keeping only elements that satisfy a condition.
Parameters:
sequence(Sequence): The sequence to filter.condition(Function): A function that returnstruefor elements to keep.
Returns:
- (Stream): A stream of elements where
conditionreturnstrue.
zip
Combines multiple sequences into a stream of tuples, stopping when the shortest sequence is exhausted.
Parameters:
*sequences(Array of Sequence): The sequences to combine.
Returns:
- (Stream): A stream of tuples, where each tuple contains corresponding elements from the input sequences.
unzip
Splits a sequence of tuples into multiple streams.
Parameters:
sequence(Sequence of Array): A sequence where each element is a tuple.numStreams:(Number, default:2): The number of streams to produce.
Returns:
- (Array of Stream): An array of
numStreamsstreams, where thei-th stream contains thei-th element from each tuple.
flatten
Flattens a sequence of sequences into a single stream.
Parameters:
sequences(Sequence of Sequence): The sequence to flatten.
Returns:
- (Stream): A stream containing all elements from the nested sequences.
dissect
Splits a sequence into chunks at elements that satisfy a condition.
Parameters:
sequence(Sequence): The sequence to process.condition(Function): A function that determines split points.
Returns:
- (Stream of Array): A stream of arrays, where each array contains a group of elements up to and including a split point.
chunk
Splits a sequence into arrays of a fixed size.
Parameters:
sequence(Sequence): The sequence to split.size(Number): The number of elements in each output array.
Returns:
- (Stream): A stream containing arrays with
sizeelements each, except that the last array may have fewer elements.
Objects
keys
Returns an array of the keys in an object.
Parameters:
object(Object): The object whose keys to retrieve.
Returns:
- (Array): An array of the object’s keys.
properties
Returns an array of the key-value pairs in the object.
Parameters:
object(Object): The object whose properties to retrieve.
Returns:
- (Array): An array of the object’s properties.
merge
Combines the properties of the specified objects into a new object.
If the same key appears in more than one input object, the resulting object takes the property value from the last such object.
Parameters:
objects(Array of Object): The objects to combine.
Returns:
- (Object): The combined object.
Indexing
at
Returns the value at the specified index in the specified collection, or a default value if the index is invalid.
Without the default value, a | at(b) is equivalent to a @ b.
Parameters:
collection(Sequence or Object): The collection to index into.index(Number or String): The index value.default:(Function or Null, defaultnull): A function to call and return the result of if the index is invalid, ornullto throw an error if the index is invalid.
Finite streams can be indexed as if they were arrays.
Infinite streams only accept positive indices. They loop forever if the index is negative.
Utilities
debug
Writes the specified value to a diagnostic log. Exactly where this goes depends on the implementation and configuration; writing to standard error is a common default.
This function returns its argument, allowing it to be dropped into pipelines temporarily without disrupting their structure. For example, 42 | foo | bar | debug | baz has the same result as 42 | foo | bar | baz, but it writes bar’s return value to the diagnostic log.
Parameters:
value(Any): The value to write.name(String or Null, defaultnull): If provided, the output value will be tagged with this, making it clearer which debug values came from where.
Returns:
- (Any): The
valueargument.
itself
Returns its argument. This is useful when a function must be provided, but no transformation is needed, and can be clearer than just writing (x) => x.
Parameters:
x(Any): The argument.
Returns:
- (Any): The argument.
callOnce
Creates a function that evaluates its body only the first time it is called, and saves the result for subsequent calls.
Parameters:
body(Function): A zero-argument function to evaluate on the first call.
Returns:
- (Function): The wrapped function.
Sets and Maps
Set
A Set is like an array, but it can’t have duplicate elements, and checking whether an element is in the set is fast regardless of the size of the set.
newSet
Creates an immutable set.
Parameters:
elements(Array, default[]): The set’s elements. Duplicate elements are silently discarded.
Returns:
- (Set): The new set.
Set/size
Returns:
- (Number): The number of elements in the set.
Set/elements
Returns:
- (Array): An array containing all the elements in the set.
Set/has
Checks whether the specified element is in the set.
Parameters:
element(Any): The value to look for.
Returns:
- (Boolean): Whether the value is in the set.
Map
A Map is a collection of key-value pairs, where keys are unique. Looking up a value by key is fast regardless of the size of the map.
newMap
Creates an immutable map.
Parameters:
entries(Array, default[]): An array of[key, value]pairs. If duplicate keys exist, only the last one is kept.
Returns:
- (Map): The new map.
Map/size
Returns:
- (Number): The number of key-value pairs in the map.
Map/keys
Returns:
- (Array): An array containing all keys in the map.
Map/values
Returns:
- (Array): An array containing all values in the map.
Map/entries
Returns:
- (Array): An array of
[key, value]pairs representing the map’s contents.
Map/has
Checks whether the specified key exists in the map.
Parameters:
key(Any): The key to check.
Returns:
- (Boolean): Whether the key is in the map.
Map/at
Retrieves the value associated with the specified key.
Parameters:
key(Any): The key whose value to retrieve.default(Function or Null, defaultnull): A function that provides a default value if the key is not found, ornullto throw an error if the key is missing.
Returns:
- (Any): The value associated with the key, or the result of calling
defaultif the key is not found.
Mutable Objects
Var
A Var holds a value that can be retrieved or updated.
newVar
Creates a mutable variable, set to the specified initial value.
Parameters:
initialValue(Any): The initial value of the variable.
Returns:
- (Var): The new variable.
Var/get
Returns the current value of the variable.
Returns:
- (Any): The current value.
Var/set
Updates the variable’s value.
Parameters:
newValue(Any): The new value to assign.
Returns:
- (Any): The updated value.
MutableArray
A mutable array allows updating arbitrary elements, adding new elements to the end, and removing elements from the end.
newMutableArray
Creates a mutable array.
Parameters:
elements(Array, default[]): The initial elements of the array.
Returns:
- (MutableArray): The new mutable array.
MutableArray/size
Returns:
- (Number): The number of elements in the array.
MutableArray/elements
Returns:
- (Array): An array containing all elements in the mutable array.
MutableArray/append
Adds an element to the end of the array.
Parameters:
element(Any): The value to append.
Returns:
- (MutableArray): The mutable array itself, for chaining.
MutableArray/set
Replaces the element at the specified index.
Parameters:
index(Number): The position to update (1-based, negative values count from the end).element(Any): The new value.
Returns:
- (MutableArray): The mutable array itself, for chaining.
Throws:
indexOutOfBounds: If the index is out of range.
MutableArray/storeAt
Alias for set, but with parameters in reversed order. Useful as the final step in a pipeline that computes the new element value.
Parameters:
element(Any): The new value.index(Number): The position to update (1-based, negative values count from the end).
Returns:
- (MutableArray): The mutable array itself, for chaining.
Throws:
indexOutOfBounds: If the index is out of range.
MutableArray/at
Retrieves the element at the specified index.
Parameters:
index(Number): The position to retrieve (1-based, negative values count from the end).default:(Function or Null, defaultnull): A function returning a default value if the index is out of range, ornullto throw an error.
Returns:
- (Any): The element at the index, or the result of
defaultif out of range.
MutableArray/pop
Removes and returns the last element.
Parameters:
default:(Function or Null, defaultnull): A function returning a default value if the array is empty, ornullto throw an error.
Returns:
- (Any): The last element, or the result of
defaultif the array is empty.
MutableArray/clear
Removes all elements from the array.
Returns:
- (MutableArray): The mutable array itself, for chaining.
MutableSet
A mutable set is like a regular set, but it allows adding and removing elements dynamically.
newMutableSet
Creates a mutable set.
Parameters:
elements(Array, default[]): The initial elements of the set. Duplicate elements are silently discarded.
Returns:
- (MutableSet): The new mutable set.
MutableSet/size
Returns:
- (Number): The number of elements in the set.
MutableSet/elements
Returns:
- (Array): An array containing all elements in the mutable set.
MutableSet/add
Adds an element to the set.
Parameters:
element(Any): The value to add.
Returns:
- (MutableSet): The mutable set itself, for chaining.
MutableSet/remove
Removes an element from the set.
Parameters:
element(Any): The value to remove.
Returns:
- (MutableSet): The mutable set itself, for chaining.
MutableSet/has
Checks whether the specified element is in the set.
Parameters:
element(Any): The value to look for.
Returns:
- (Boolean): Whether the value is in the set.
MutableSet/clear
Removes all elements from the set.
Returns:
- (MutableSet): The mutable set itself, for chaining.
MutableMap
A mutable map is a collection of key-value pairs where keys are unique, and entries can be added, updated, and removed dynamically.
newMutableMap
Creates a mutable map.
Parameters:
entries(Array, default[]): An array of[key, value]pairs to initialize the map.
Returns:
- (MutableMap): The new mutable map.
MutableMap/size
Returns:
- (Number): The number of entries in the map.
MutableMap/keys
Returns:
- (Array): An array containing all keys in the map.
MutableMap/values
Returns:
- (Array): An array containing all values in the map.
MutableMap/entries
Returns:
- (Array): An array of
[key, value]pairs representing the map’s entries.
MutableMap/set
Sets the value for a given key.
Parameters:
key(Any): The key to set.value(Any): The value to associate with the key.
Returns:
- (MutableMap): The mutable map itself, for chaining.
MutableMap/storeAt
Alias for set, but with parameters in reversed order. Useful as the final step in a pipeline that computes the new element value.
Parameters:
value(Any): The value to store.key(Any): The key to associate with the value.
Returns:
- (MutableMap): The mutable map itself, for chaining.
MutableMap/remove
Removes a key and its associated value from the map.
Parameters:
key(Any): The key to remove.
Returns:
- (MutableMap): The mutable map itself, for chaining.
MutableMap/has
Checks whether the map contains a specific key.
Parameters:
key(Any): The key to check.
Returns:
- (Boolean): Whether the key exists in the map.
MutableMap/at
Retrieves the value associated with a given key.
Parameters:
key(Any): The key to look up.default:(Function or Null, defaultnull): A function returning a default value if the key is not found, orNullto throw an error.
Returns:
- (Any): The value associated with the key, or the default value if the key is not found.
MutableMap/clear
Removes all entries from the map.
Returns:
- (MutableMap): The mutable map itself, for chaining.
also
Performs an action on a value, then returns it for further processing.
Parameters:
value(Any): The value to perform the action on.action(Function): The function to apply.
Returns:
- (Any): The
valueargument.
Errors
newError
Creates an error value with the specified error type and details. This in itself doesn’t throw the error.
Parameters:
type(String): The kind of error condition that this error represents.**details(Object): Any relevant information about the cause of the error.
Returns:
- (Error): The error value, an
Instancewith the specifiedtypeanddetailsproperties.
throw
Throws an error.
Parameters:
error(Error): The error to throw.
Returns:
- (Never): Never returns.
try
Calls the specified function, then invokes one of the specified handlers depending on whether the function threw an error.
Parameters:
f(Function): The function to call.onError:(Function): The handler to invoke if the function throws an error.onSuccess:(Function or Null, defaultnull): The handler to invoke if the function returns normally, ornullto simply return the function’s result.
catch
Calls the specified function, returning {status: "success", value: <value>} if the function returns normally, or {status: "error", error: <error>} if the function throws an error.
This is useful if the result of a fallable operation needs to be stored somewhere for later processing.
Parameters:
f(Function): The function to call.
Returns:
- (Object): An object with the status and value or error.
Validation
Kenpali is a dynamically typed language, but it does strict type checks at runtime. The core module exposes several functions to interact with the type checking system.
Values are checked against a schema. Valid schemas are:
- A Kenpali type: one of the primitive classes
Null,Boolean,Number,String,Array,Object, orFunction; or an instance type such asError,Class, orMap; or a protocol such asSequenceorType. - An object of the form
{form: "enum", values: [<values>]}, which matches only the specified values. - An object of the form
{form: "union", options: [<schemas>]}, which matches a value if at least one of the specified schemas matches it. - An object of the form
{form: "condition", schema: <schema>, condition: <function>}, which adds the specified condition to the schema. For example,{form: "condition", schema: Number, condition: | lt(10)}matches only numbers less than 10. - An object of the form
{form: "array", elements: <schema>}, which matches only arrays whose elements all match the specified schema. For example,{form: "array", elements: Number}matches only arrays of numbers. - An object of the form
{form: "tuple", shape: [<schemas>]}, which matches only arrays whose elements match the specified schemas in order. For example,{form: "tuple", shape: [Number, String]}matches only arrays whose first element is a number and whose second element is a string. - An object of the form
{form: "object", keys: <key-schema>, values: <value-schema>}, which matches only objects whose keys and values match the specified schemas. Eitherkeysorvaluesmay be omitted;keysdefaults toString, andvaluesdefaults toAny. For example,{form: "object", values: Number}matches only objects whose whose values are numbers, while{form: "object", keys: {form: "enum", values: ["foo", "bar", "baz"]}, values: Number}matches only objects whose keys are some subset of"foo","bar", and"baz"and whose values are numbers. - An object of the form
{form: "record", shape: {<property-schemas>}}, where each property of the shape is a schema that the corresponding property must match. For example,{form: "record", shape: {foo: Number, bar: String}}matches only objects with a numericfooproperty and a stringbarproperty.
validate
Ensures that the specified value matches a schema. Throws a validation error if the value doesn’t match.
Parameters:
value(Any): The value to check.schema(Type or Object): The schema to check against.
Returns:
- (Boolean): Always
true.
matches
Checks whether the specified value matches a schema.
Parameters:
value(Any): The value to check.schema(Type or Object): The schema to check against.
Returns:
- (Boolean): Whether the value matches the schema.
oneOfValues
Creates a schema that checks if the value is in the specified list. This can be used to simulate an “enum” type.
Parametersː
*values(Array of Any): The allowed values.
Returns:
- (Object): A schema of the form
{form: "enum", values: [<values>]}.
either
Creates a schema that allows anything matching any of the specified schemas.
Parameters:
*schemas(Array of Type or Object): The allowed schemas.
Returns:
- (Object): A schema of the form
{form: "union", options: [<schemas>]}.
satisfying
Creates a condition schema, adding the specified predicate to the schema.
Parameters:
schema(Type or Object): The schema to add the condition to.condition(Function): A predicate that the value must satisfy.
Returns:
- (Object): A schema of the form
{form: "condition", schema: <schema>, condition: <function>}.
arrayOf
Creates a schema that checks all the elements of an array against a single schema.
Parameters:
elements(Type or Object): The schema that all elements must match.
Returns:
- (Object): A schema of the form
{form: "array", elements: <schema>}.
tupleLike
Creates a schema that checks each element of an array against a separate schema.
Parameters:
shape(Array of Type or Object): A schema that each element of the array must match.
Returns:
- (Object): A schema of the form
{form: "tuple", shape: [<schemas>]}.
objectOf
Creates a schema that checks the property values of an object against a single schema, and optionally that the keys match a schema and.
Parameters:
keys:(Type or Object, default:String): The schema that all keys must match.values:(Type or Object): The schema that all values must match.
Returns:
- (Object): An object of the form
{form: "object", keys: <key-schema>, values: <value-schema>}.
recordLike
Creates a schema that checks each property of an object against a separate schema.
Parameters:
shape(Object of Type or Object): A schema that each property of the object must match.
Returns:
- (Object): A schema of the form
{form: "record", shape: {<entry-schemas>}}.
optional
Creates a schema that marks a tuple element or record property as optional.
The returned schema is only valid inside the shape property of a tuple or record schema.
Parameters:
schema(Type or Object): The schema that the element or property must match if present.
Returns:
- (Object): A schema of the form
{form: "optional", schema: <schema>}.