Built-in Values
Every Whim value has a runtime type. A declaration can state which values it accepts. Whim checks that rule when the program reaches the boundary.
Scalar values
Whim has seven scalar value kinds.
| Type | Values |
|---|---|
null | null |
bool | true and false |
int | signed 64-bit integers |
uint | unsigned 64-bit integers, from 0 through 18,446,744,073,709,551,615 |
float | double-precision floating-point numbers |
string | byte strings |
fresh | opaque identities created by fresh!() |
Integers and floats stay distinct:
assert!(1 is int);
assert!(1u is uint);
assert!(1.0 is float);
assert!(1u != 1);
assert!(1 != 1.0);
Strings hold bytes, not a promise of valid UTF-8. The source file is UTF-8, but a string may contain any byte through escapes, file reads, sockets, or binary decoding.
fresh!() creates an identity distinct from every identity this VM has already
created. Copying it preserves that identity:
$a = fresh!();
$b = fresh!();
$copy = $a;
assert!($a is fresh);
assert!($a != $b);
assert!($a == $copy);
$names = dict[$a => 'first', $b => 'second'];
assert!($names[$copy] == 'first');
Fresh values support == and !=, type checks, and dictionary keys. They have
no order, arithmetic, bit operations, or implicit string or bool conversion.
Even copies reject order comparisons such as $a <= $copy and $a <=> $copy.
They cannot index a vec, tuple, or string.
$a as uint gives an unsigned integer for explicit use with APIs that need
one. Equal identities give equal integers, and distinct identities give
distinct integers during that VM lifetime. The integer has no promised value
across runs and gives no ordering contract. Casting an integer back to fresh
fails, including an integer obtained from a fresh value. Casting a fresh value
to fresh preserves it.
If the VM exhausts its identity space, fresh!() throws OverflowError;
further calls also fail. Separate VMs may reuse representations. Fresh values
are not persistent IDs, distributed IDs, or secrets.
Whim\Refine\Scalar and Whim\Refine\ArrayKey include fresh.
Whim\Refine\Numeric does not. JSON and BSON reject fresh values and keys;
cast explicitly to a supported type when encoding a diagnostic representation.
Such an encoding cannot restore the identity.
Arrays
Whim has three array forms:
| Type | Meaning |
|---|---|
(A, B) | an immutable, fixed-size tuple |
vec<T> | a mutable list with uint keys from zero |
dict<K, V> | a mutable, ordered key-value map |
array<K, V> accepts a tuple, vec, or dict whose keys and values fit K and
V.
$pair = ('Ada', 36);
$names = vec['Ada', 'Grace'];
$scores = dict['Ada' => 10, 'Grace' => 12];
assert!($pair is (string, int));
assert!($names is vec<string>);
assert!($scores is dict<string, int>);
The collections chapter covers their syntax and update rules.
Objects and callables
object accepts any class instance. A class or interface name accepts objects
of that class or its subtypes.
An object shape, such as
#{ name: string, ... }, checks public instance properties and their current
values. Omit ... to require exactly the listed public properties.
fn(A, B): R accepts a callable with two parameters and result R:
function apply(fn(int): int $operation, int $value): int {
return $operation($value);
}
$double = fn(int $value): int => $value * 2;
assert!(apply($double, 21) == 42);
classname<T> accepts a class name whose instances satisfy T.
Wide and empty types
mixed accepts every value. !never also means every value.
never accepts no value. A function with return type never cannot return.
It must throw, exit, or keep running.
void is valid only as a function or method return. Such a callable returns no
value. You cannot use void for a parameter or property.
Literal types
A scalar value may also act as a type:
function choose('yes'|'no' $answer): bool {
return $answer == 'yes';
}
assert!(choose('yes'));
true, 42, 42u, and 'yes' each describe one value. Literal types make unions,
ranges, enum cases, and constants precise.
String length types
Put an integer or integer range after string to limit its byte length:
| Type | Accepted strings |
|---|---|
string[0] | empty strings |
string[5] | strings with five bytes |
string[1..] | strings with at least one byte |
string[1..=64] | strings with one through 64 bytes |
The range uses the same bounds as an integer range. Its lower bound is
inclusive. .. excludes the upper bound, while ..= includes it.
Whim treats string[0] as '', string[1..] as string&!'', and
string[0..] as string.
String lengths count bytes. For example, the UTF-8 form of é has two bytes:
assert!('é' is string[2]);
String length types work in aliases, parameters, properties, generic bounds, casts, and patterns.
Conditions
Conditions must be bool. Whim has no truthy or falsy conversion:
$name = 'Ada';
if ($name) {
write_line!($name);
}
Write the test you mean:
$name = 'Ada';
if ($name != '') {
write_line!($name);
}
This rule also applies to while, do ... while, &&, ||, &&=, and
||=.