Skip to main content

Primitives

Primitives are fundamental types that just exist. These types cannot be expressed as composites of other types.

Bool

Booleans are represented by the Bool type, which can take on the values True and False.

let x = True
let y = False

Int

Integers are represented by the Int type, which is an arbitrary precision signed integer (commonly referred to as a bignum). By default, integers are specified in decimal (base 10). Case-sensitive prefixes of 0b for binary (base 2), 0o for octal (base 8), and 0x for hexadecimal (base 16) may be used. Underscores (_) may appear anywhere in the literal except before the first digit, after the last digit, and before, between, or after the characters of the 0b, 0o, and 0x prefixes. Multiple underscores may appear consecutively.

0 50 1_000_000                      // Decimal
0b10101010 0b1111_0110 // Binary
0o12345670 0o123_005_774 // Octal
0x1234567890abcdefABCDEF 0xfe_23_06 // Hexadecimal

1_2__3___4 // Multiple underscores may appear consecutively.

Float

A Float is an IEEE 754 floating-point number with at least double precision (i.e., 64 bits). A Float literal must include either a . or e (or both) to distinguish it from an integer literal. Underscores (_) can be used to separate digits and may appear anywhere in the literal except before the first digit, after the last digit, immediately after the . (radix point), and before, between, or after the characters of the e, e+, and e-.

0.0 23.45 1_057.1 3.141_593  // Regular
1e9 2.5e-4 2_712.349_753e+10 // Scientific

6___.7_8__9e4__5 // Excessive underscores for some reason.

String

A String represents textual data encoded in UTF-8. String literals use double quotes ("...") and may contain Unicode characters.

let s1 = "🍉 is a watermelon"
let s2 = "\u{1F349} is a watermelon"
assert_eq(s1, s2)

String escapes

Escapes are used to insert values that may not be ambiguous to express via regular text. For example, \" escapes the double quote and the resulting value of this sequence is ". There are several escapes that can be used.

  • \n: Newline (U+000A).
  • \r: Carriage return (U+000D).
  • \t: Tab (U+0009).
  • \\: Backslash (\).
  • \0: Null (U+0000).
  • \': Single quote (').
  • \": Double quote (").
  • \u{XXXXXX}: Unicode escape of up to 24 bits, where each X is a hex digit. There can be 1 to 6 hex digits in the curly braces.
  • \x{XX}: 1 byte where each X is a hex digit.
  • \x{XXYY}: 2 bytes where each X and Y is a hex digit. This is equivalent to \x{XX}\x{YY}. In general, there may be arbitrarily many Xs; however, there must be an even number of them to guarantee an integer number of bytes.

Strings spanning multiple lines

When a string spans multiple lines, all lines are joined by a space. Leading whitespace on continuing lines, trailing whitespace on non-terminal lines, and empty lines are ignored. Escapes such as \n and \u{...} are preserved.

// Strings spanning multiple lines are joined with a space.
let s1 = "apples
bananas cherries "
let s2 = "apples bananas cherries"
assert_eq(s1, s2)

Block strings

Block strings use three double quotes to delimit the start and end. The following whitespaces are stripped: leading whitespace before the first non-whitespace line of text, leading whitespace common to the start of each line, trailing whitespace on each line, trailing whitespace after the last non-whitespace line of text, and carriage returns (U+000D) are stripped. Carriage returns included by an escape, such as \r, are respected.

let s1 = """
text that
is spread
across
several lines
"""
let s2 = " text that\n is spread\nacross\n several lines"
assert_eq(s1, s2)

Raw strings

Raw strings are delimited with r"..." and do not process any escapes. There can be 0 or more # between the r and opening ", and the same number of # must appear after the closing #. Carriage returns (U+000D) are removed. The same whitespace processing rules as Strings enclosed in "..." are applied.

assert_eq(r"no \n escapes", "no \\n escapes")
assert_eq(r#"nested r"raw" string "#, "nested r\"raw\" string")

Bytes

Bytes are similar to strings but store arbitrary binary data. Bytes literals look like String literals with a b prefix. Unlike a String, Bytes may contain arbitrary binary data. Bytes literals, however, can consist of only ASCII literal characters. The \u{...} and \x{...} escapes must be used to encode Unicode (or other character sets). The same whitespace processing rules as Strings enclosed in "..." are applied to Bytes.

let b1 = b"this is not
\x{FF}
valid Unicode"
let b2 = b"this is not \x{FF} valid Unicode"
assert_eq(b1, b2)

Raw bytes

Raw byte strings can also be constructed using the same rules as raw strings, but with a br prefix. The same whitespace processing rules as Strings enclosed in "..." are applied.

assert_eq(br"no \n escapes", b"no \\n escapes")
assert_eq(br#"nested br"raw byte" string "#, b"nested br\"raw byte\" string")