Basic types

Primitive types

The primitive types are:

bool Boolean type; false or true.
char8 Single byte in a UTF-8 string. This is not a numeric type.
nat8, nat16, nat32, nat64 Natural numbers, in the range 0 to 2n - 1. nat is short for nat64.
int8, int16, int32, int64 Integers, in the range -2n - 1 to 2n - 1 - 1. int is short for int64.
float32, float64 Floating-point values. float is short for float64.

Arithmetic

nat and int arithmetic always returns an exactly correct result or throws an exception.

main void() a nat8 = 255 _ = a + 1

float arithmetic doesn't have such checks, since floats are usually expected to be inexact.

Conversion

There is no dedicated syntax for conversion, but a function should be named to if it does an obvious conversion.
This relies on type inference which will be explained more in Type inference.

main void() n nat = 3 i int = n to f float = i to # "Conversion" to string is usually called `show` instead of `to` s string = "{f}" info log s

As with arithmetic, conversions between nat/int types will throw if they can't return an exact result.

main void() i int = -3 _ nat = i to

Strings

These are similar to other programming languages. Strings are represented as a char8[], but when iterated they decode to char32s.
(In a JavaScript build, strings represented as are JS strings.)

String syntax

Basic string syntax is similar to C: "hello".
They support the same escape sequences, like "hello\nworld".

There are also triple-quoted strings that allow newlines in the string.

main void() info log "hello\nworld" info log """ I wrote a haiku about programming in crow but I forgot it """

String interpolation

You've seen this a lot already.
"1 + 1 is {1 + 1}!" is shorthand for ("1 + 1 is ", (1 + 1).show, "!") interpolate.
(interpolate just concatenates its inputs.) show is a conventional name for a function that renders its argument to a string.

String functions

String functions are in string.
A string is also a collection of char32, so many functions in col/collection will work on strings.

Symbols

Strings are often used simply as identifiers or like ad-hoc enums. In crow, you should instead use symbols for those use cases.
A symbol is a unique identifier that comes from a string.
The string is interned, meaning that two separately-allocated strings that are equal will only result in a single allocated symbol.
So, two symbols are equal if their pointers are equal. That means == on symbols is fast, making them good as a key in a map.

The literal syntax for a symbol is the same as for a string.

main void() info log "{"left" opposite}" opposite symbol(a symbol) # This will be fast since it compares symbols by identity. if a == "left" "right" elif a == "right" "left" else "nowhere"

As usual, to convert between strings and symbols, call the to function.

Tuples

You've already seen tuples in the section on destructuring in Local variables.
The syntax for a tuple type is like (nat, string) or (nat, string, float). It can have up to 9 members. It can't have less than 2.

A tuple type is often created implicitly by a destructuring, as in n nat, s string declaring a (nat, string) tuple.

main void() tuple (nat, string) = 0, "a" n nat, s string = tuple # '==' compares each member info log "{tuple == (n, s)}"