Literals and Operators
Integers 1
, floats 1.2
, imaginary numbers 3i
, runes 'a'
, strings "abc"
, booleans true
, and the nil
value.
Integers can be expressed using binary, octal, decimal, dozenal, or hexadecimal notation using either of these prefixes: 0b
, 0o
, 0d
, 0z
, or 0x
, respectively.
Underscores can be inserted in numeric literals to improve readability, e.g. 1_000
is the same as 1000
, and0b1010_1110
is the same as 0b10101110
.
Number literals and constants in Odin "just work" in that if a constant is "untyped", it can convert to the appropriate type.
import "fmt.odin";
main :: proc() {
FOO :: 123; // named "untyped" constant
BAR: int : 456; // named constant of type `int`
// Constant values are calculated at compile time rather than runtime.
DUH :: FOO + BAR; // `DUH` will be of type `int` because `BAR` is typed
// Addition
fmt.println("1+1 =", 1 + 1);
// Subtraction
x: i32 = 1;
fmt.println("1-2 =", x-2);
// TODO: Try changing the type of the constant `x` to `u32` and see what happens
// TODO: Try changing `x` to a variable rather than a constant and change the type to `u32`
// Short-circuiting boolean logic
fmt.println("true AND false is", true && false);
fmt.println("true OR false is", true || false);
fmt.println("NOT true is", !true);
// Bitwise operations
fmt.printf("0011 AND 0101 is %b\n", 0b0011 & 0b0101);
fmt.printf("0011 OR 0101 is %b\n", 0b0011 | 0b0101);
fmt.printf("0011 XOR 0101 is %b\n", 0b0011 ~ 0b0101);
fmt.printf("0011 AND-NOT 0101 is %b\n", 0b0011 &~ 0b0101);
fmt.printf(Complement of 0011 is %b\n, ~cast(byte)i); // enforce `byte` and not default `int`
fmt.printf("1 << 5 is", 1 << 5);
fmt.printf("0x70 >> 2 is", 0x70 >> 2);
// Use underscores for readability
fmt.println("One billion is", 1_000_000_000);
// Complex numbers
c1: complex64 = 1 + 2i; // Complex numbers
c2 := 3 + 4i; // default type `complex128`
c3 := complex(3, 4); // Alternate form
c3_real := real(c3); // Returns the real component of `c3`
c3_imag := imag(c3); // Returns the imaginary component of `c3`
fmt.println("A complex number: " c3);
// Extended complex numbers
q1: quaternion128 = 1 + 2i + 3j - 4k; // Quaternion literal
q2 := 1 + 3j; // default type `quaternion256`
q3 := quaternion(1, -, 3, -4); // Alternate form
q3_real := real(c3); // Returns the real component of `q3`
q3_imag := imag(c3); // Returns the i-imaginary component of `q3`
q3_jmag := jmag(c3); // Returns the j-imaginary component of `q3`
q3_kmag := kmag(c3); // Returns the k-imaginary component of `q3`
fmt.println("A quaternion number: " c3);
}
Strings
There two kinds of string literals, escaped and raw.
// An escaped string can only be on one line
x := "Escaped string\n";
// A raw string can cover multiple lines
y := `Raw string
`;
// String literals can be automatically merged if necessary
z := "Append one string" " with another really easily";
Unary Operators
Left association unary operators have the highest precedence, then right association unary operators.
Operator(s) | Description | Associates |
---|---|---|
^ | Address | Right |
^ | Dereference | Left |
+ - ! ~ | Add, Negate, Not, Complement | Right |
Note: -x^
is evaluated like -(x^)
.
Binary Operators
If an operator has the same precedence, the evaluation order will be left to right.
Precedence | Operator(s) | Description | ||
---|---|---|---|---|
2 | \ | \ | Logical or | |
3 | && | Logical and | ||
4 | == != < > <= >= | Comparison | ||
5 | + - \ | ~ | Add, Subtract, Bitwise or, Bitwise xor | |
6 | * / % %% & &~ << >> | Multiple, Divide, Modulo Dividend, Modulo Divisor, Bitwise and, Bitwise and not, Left shift, Right shift |
Ternary Operators
Precedence | Operator(s) | Description |
---|---|---|
1 | ?: | Conditional |
?:
is the only ternary operator in Odin. It can be used as an inline if
statement.
cond := true;
x := cond ? 123 : 321;
If the condition and values are constant, then the ternary expression can be evaluated at compile time.
MAGIC :: ODIN_OS == "windows" ? 1001 : 1000;