Basic types
Noodle’s basic value types cover completion, truth values, integers, floating-point numbers, Unicode code points, and text. They are distinct static types: Noodle never silently converts one into another.
The default standard library’s Prelude makes their conventional source names available. Prelude and modules explains that relationship in detail.
Unit has one value, written (). It represents a computation that completes
without returning meaningful data:
func announce() -> Unit do Console.println("ready");endA block with no tail expression also produces Unit, so effect-only functions
normally end with a semicolon-terminated statement rather than an explicit
().
Bool has the literals true and false. Conditions require an actual
Bool; numbers, strings, and other values are not treated as truthy:
func access_label(allowed : Bool) -> String do if allowed then "allowed" else "denied" endendBoolean operators are ! for negation, && for conjunction, and || for
disjunction. && and || short-circuit, so the right side is evaluated only
when needed.
Int is a signed 32-bit integer. Decimal, hexadecimal, and binary literals
all produce Int values:
func main() -> Unit do decimal = 42; hexadecimal = 0x2a; binary = 0b101010; Debug.trace(decimal == hexadecimal && hexadecimal == binary);endArithmetic operators include +, -, *, /, and %. Integer division
truncates toward zero. Noodle defines the result of overflow and division by
zero; these operations do not raise an arithmetic runtime error.
Wrapping arithmetic
Section titled “Wrapping arithmetic”Int values range from -2147483648 through 2147483647. Addition,
subtraction, multiplication, and unary negation use wrapping arithmetic. The
mathematical result is reduced modulo 2^32, then the resulting 32 bits are
interpreted as a signed two’s-complement value.
func main() -> Unit do Debug.trace(2147483647 + 1); Debug.trace(-2147483648 - 1); Debug.trace(50000 * 50000); Debug.trace(-(-2147483648));endThe four results are, in order:
-21474836482147483647-1794967296-2147483648Wrapping applies to a value produced by an operation. It does not make every
integer literal valid: 2147483648 is rejected at compile time. Its magnitude
is accepted only as the direct operand of -, which allows the minimum value
-2147483648 to be written.
Division and remainder
Section titled “Division and remainder”For a nonzero divisor, / performs signed integer division and discards the
fractional part toward zero. % returns the corresponding remainder. A
nonzero remainder has the sign of the dividend, the left operand:
func main() -> Unit do Debug.trace(7 / 3); Debug.trace(-7 / 3); Debug.trace(-7 % 3); Debug.trace(7 % -3);endThese expressions produce 2, -2, -1, and 1. For every nonzero
right, division and remainder satisfy:
left == (left / right) * right + (left % right)When the divisor is zero, both operations evaluate to 0:
func main() -> Unit do Debug.trace(42 / 0); Debug.trace(42 % 0); Debug.trace(0 / 0);endAll three results are 0. No error is thrown, and the result does not retain
enough information to distinguish division by zero from an ordinary zero
result. Check the divisor before the operation when zero is invalid for the
application, and represent that case explicitly with a type such as
Option or Result.
There is one overflowing division boundary: -2147483648 / -1 wraps to
-2147483648; the corresponding remainder is 0.
Comparisons use ==, !=, <, <=, >, and >= and produce Bool.
Double
Section titled “Double”Double uses binary64 floating-point values. A decimal point or exponent
distinguishes a Double literal:
func circle_area(radius : Double) -> Double do 3.141592653589793 * radius * radiusendInt and Double are different types. Write an explicit conversion such as
value.to_double() when one is required. Lossy operations such as
floor_to_int() and truncate_to_int() state their rounding behavior in the
method name.
More numeric helpers are listed in Strings and characters, alongside the standard conversion methods.
Char represents one Unicode code point and uses single quotes:
func main() -> Unit do latin = 'N'; emoji = '😀'; Debug.trace(latin); Debug.trace(emoji);endA character is not an integer or a one-character string. The standard library
provides explicit to_int() and to_string() conversions, plus
Char.from_codepoint. See
Strings and characters.
String
Section titled “String”String is immutable Unicode text and uses double quotes. ++ concatenates
two strings:
func greeting(name : String) -> String do "Hello, " ++ name ++ "!"endRaw multiline strings
Section titled “Raw multiline strings”Use a raw string when text contains quotes, backslashes, comment markers, or several physical lines that should be copied without escape processing:
func message() -> String do #|first line #|second line with "quotes" and \\slashes #|endThe #| prefix is structural and is removed from each line. Consecutive
prefixed lines are joined with \n; the final empty #| line requests a
trailing newline. Raw strings can appear anywhere a string literal is
accepted, including test names and attribute arguments.
Strings do not expose integer indexing or a code-point length() operation.
The standard library uses Unicode-aware cursors and provides joining,
iteration, slicing, and conversion APIs in
Strings and characters.
Type equality and explicit conversions
Section titled “Type equality and explicit conversions”An annotation checks a type; it does not request conversion:
func main() -> Unit do count : Int = 42; ratio : Double = count.to_double(); Console.println(ratio.to_string());endThe available conversion method depends on the source type’s associated standard-library extensions. Conversion is kept visible at the call site.
Types introduced later
Section titled “Types introduced later”These basic types are enough to understand bindings and function boundaries. Other important types are introduced where their behavior becomes useful:
- Records and tuples are structural language types;
- Datatypes define nominal alternatives;
- Arrays are standard-library collection views over the language’s array representation;
- Option and Result model absence and success-or-error outcomes;
- Task and AsyncResult model asynchronous work.
Next: values and bindings.