Rune types
Types in Rune are identified uniquely by their item. An item path is a
scope-separated identifier, like std::f64
. This particular item identifies
a type.
These items can be used to perform basic type checking using the is
and is not
operations, like this:
assert!(() is Tuple, "tuples should be tuples");
assert!((1, 2) is Tuple, "tuples should be tuples");
assert!(true is bool, "bools should be bools");
assert!('a' is char, "chars should be chars");
assert!(b'a' is u64, "bytes should be unsigned integers");
assert!(42 is i64, "integers should be integers");
assert!(42.1 is f64, "floats should be floats");
assert!("hello" is String, "strings should be strings");
assert!("x" is not char, "strings are not chars");
assert!(#{"hello": "world"} is Object, "objects should be objects");
assert!(["hello", "world"] is Vec, "vectors should be vectors");
$> cargo run -- run scripts/book/types/types.rn
Conversely, the type check would fail if you're providing a value which is not of that type.
assert!(["hello", "world"] is String, "vectors should be strings");
$> cargo run -- run scripts/book/types/bad_type_check.rn
== ! (panicked `assertion failed: vectors should be strings` (at 12)) (133.3µs)
error: virtual machine error
┌─ scripts/book/types/bad_type_check.rn:2:5
│
2 │ assert!(["hello", "world"] is String, "vectors should be strings");
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ panicked `assertion failed: vectors should be strings`
This gives us insight at runtime which type is which, and allows Rune scripts to make decisions depending on what type a value has.
fn dynamic_type(n) {
if n is String {
"n is a String"
} else if n is Vec {
"n is a vector"
} else {
"n is unknown"
}
}
println!("{}", dynamic_type("Hello"));
println!("{}", dynamic_type([1, 2, 3, 4]));
println!("{}", dynamic_type(42));
$> cargo run -- run scripts/book/types/type_check.rn
n is a String
n is a vector
n is unknown
A tighter way to accomplish this would be by using pattern matching, a mechanism especially suited for many conditional branches. Especially when the branches are different types or variants in an enum.
fn dynamic_type(n) {
match n {
n if n is String => "n is a String",
n if n is Vec => "n is a vector",
_ => "n is unknown",
}
}
println!("{}", dynamic_type("Hello"));
println!("{}", dynamic_type([1, 2, 3, 4]));
println!("{}", dynamic_type(42));
$> cargo run -- run scripts/book/types/type_check_patterns.rn
n is a String
n is a vector
n is unknown