Expressions
Joule is expression-oriented. Most constructs return a value, including if, match, and blocks.
Literals
42 // integer (i32)
3.14 // float (f64)
true // bool
'A' // char
"hello" // String
Integer Literal Suffixes
42i8 42i16 42i32 42i64 42isize
42u8 42u16 42u32 42u64 42usize
Float Literal Suffixes
3.14f32 3.14f64
Arithmetic Operators
| Operator | Operation | Types |
|---|---|---|
+ | Addition | integers, floats, String concatenation |
- | Subtraction | integers, floats |
* | Multiplication | integers, floats |
/ | Division | integers, floats |
% | Remainder | integers |
** | Exponentiation | integers, floats (right-associative) |
Comparison Operators
| Operator | Operation |
|---|---|
== | Equal |
!= | Not equal |
< | Less than |
> | Greater than |
<= | Less or equal |
>= | Greater or equal |
All comparison operators return bool.
Logical Operators
| Operator | Operation |
|---|---|
&& | Logical AND (short-circuit) |
|| | Logical OR (short-circuit) |
! | Logical NOT |
Bitwise Operators
| Operator | Operation |
|---|---|
& | Bitwise AND |
| | Bitwise OR |
^ | Bitwise XOR |
~ | Bitwise NOT |
<< | Left shift |
>> | Right shift |
Pipe Operator
The pipe operator |> passes the result of the left-hand expression as the first argument to the right-hand function:
// Without pipe
let result = process(transform(parse(input)));
// With pipe -- reads left to right
let result = input |> parse |> transform |> process;
Pipe with Multi-Argument Functions
When the right-hand side is a call with arguments, the piped value is inserted as the first argument:
let result = data
|> filter(|x| x > 0)
|> map(|x| x * 2)
|> take(10);
Pipe Precedence
The pipe operator has lower precedence than all other operators except assignment. It is left-associative:
// These are equivalent:
a |> f |> g
g(f(a))
Assignment
let mut x = 0;
x = 42;
Compound assignment is not supported. Use x = x + 1 instead of x += 1.
Block Expressions
A block evaluates to its last expression:
let result = {
let a = 10;
let b = 20;
a + b // no semicolon -- this is the block's value
};
// result == 30
If Expressions
if is an expression and returns a value:
let max = if a > b { a } else { b };
Without else, the type is ():
if condition {
do_something();
}
Chained:
if x > 0 {
"positive"
} else if x < 0 {
"negative"
} else {
"zero"
}
Match Expressions
Exhaustive pattern matching:
let name = match color {
Color::Red => "red",
Color::Green => "green",
Color::Blue => "blue",
};
See Patterns for pattern syntax.
Loops
While Loop
while condition {
body();
}
For Loop
for item in collection {
process(item);
}
Loop (Infinite)
loop {
if done() {
break;
}
}
Break and Continue
loop {
if skip_this() {
continue;
}
if finished() {
break;
}
}
Function Calls
let result = add(1, 2);
Method Calls
let len = string.len();
let upper = string.to_uppercase();
Field Access
let x = point.x;
let name = person.name;
Index Access
let first = vec[0];
let char = string[i];
Struct Construction
let p = Point { x: 3.0, y: 4.0 };
Enum Variant Construction
let c = Shape::Circle { radius: 5.0 };
let ok = Result::Ok(42);
Return
Explicit return from a function:
fn find(items: Vec<i32>, target: i32) -> Option<i32> {
let mut i = 0;
while i < items.len() {
if items[i] == target {
return Option::Some(items[i]);
}
i = i + 1;
}
Option::None
}
Type Cast
let x = 42i32 as f64;
let y = offset as usize;