Expressions
Chuks uses an expression-based design, meaning that many constructs typically treated as statements in other languages are actually expressions that produce values. This is similar to languages like Rust and Kotlin.
What Does “Expression-Based” Mean?
Section titled “What Does “Expression-Based” Mean?”In most C-family languages, an if block is a statement — it performs an action but doesn’t return a value. In Chuks, if, while, for, for-of, and for-in are all expressions — they evaluate to a value and can be used anywhere a value is expected.
// if as an expression — the result is assigned to a variablevar status = if (score >= 90) { "A"} else if (score >= 80) { "B"} else { "C"}println(status) // "A", "B", or "C"When used as a standalone line (without assigning the result), these expressions are automatically wrapped in an ExpressionStatement — so you can still use them exactly like traditional statements.
// if used as a statement (result is discarded)if (x > 0) { println("positive")}Expressions vs Statements
Section titled “Expressions vs Statements”Chuks distinguishes between expressions (which produce values) and statements (which perform actions).
Expressions (produce a value)
Section titled “Expressions (produce a value)”| Expression | Example |
|---|---|
| Literals | 42, "hello", true, [1, 2, 3] |
| Identifiers | x, myVar |
| Binary operations | a + b, x > 0 |
| Unary operations | -x, !done |
| Function calls | greet("Chuks") |
| Method calls | arr.push(5) |
| Property access | arr.length, user.name |
| Index access | arr[0], map["key"] |
| Slice expression | arr[1:3], str[:5] |
| Ternary | cond ? a : b |
| Assignment | x = 5 |
| If / Else | if (cond) { a } else { b } |
| While loop | while (cond) { ... } |
| For loop | for (init; cond; update) { ... } |
| For-of loop | for (item of collection) { ... } |
| For-in loop | for (key in map) { ... } |
| Lambda | (x: int): int => x * 2 |
| Spawn | spawn fetchData() |
| Await | await task |
Statements (perform actions, no value)
Section titled “Statements (perform actions, no value)”| Statement | Example |
|---|---|
| Variable declaration | var x: int = 5 |
| Constant declaration | const pi = 3.14 |
| Function declaration | function add(a: int, b: int): int { ... } |
| Class declaration | class Dog extends Animal { ... } |
| Return | return value |
| Import | import "math" |
| Interface declaration | interface Printable { ... } |
| Enum declaration | enum Color { Red, Green, Blue } |
| Expression statement | println("hello") (an expression used as a statement) |
Comparison With Other Languages
Section titled “Comparison With Other Languages”| Feature | Java / C# | JavaScript | Rust | Kotlin | Chuks |
|---|---|---|---|---|---|
if as expression | No | No¹ | Yes | Yes | Yes |
while as expression | No | No | Yes (returns ()) | No | Yes |
for as expression | No | No | No² | No | Yes |
| Ternary operator | a ? b : c | a ? b : c | N/A (use if) | N/A (use if) | Yes (a ? b : c) |
| Slice expressions | N/A | a.slice() | &a[1..3] | N/A | Yes (a[1:3]) |
¹ JavaScript has the ternary operator ? : but if itself is a statement.
² Rust has for loops but they return (), not a meaningful value.
Ternary Operator
Section titled “Ternary Operator”Chuks supports both the traditional ternary operator (? :) and if-expressions for inline conditionals:
// Ternary operatorvar label = count == 1 ? "item" : "items"
// Equivalent if-expressionvar label2 = if (count == 1) { "item" } else { "items" }Ternary expressions are right-associative and can be nested:
var grade = score >= 90 ? "A" : score >= 80 ? "B" : "C"Operators
Section titled “Operators”Chuks provides a standard set of operators that evaluate to values.
Arithmetic
Section titled “Arithmetic”Arithmetic operators evaluate to the numeric result of the operation.
+(Addition),-(Subtraction),*(Multiplication),/(Division),%(Modulo)
var sum = 10 + 5;var rem = 10 % 3;Comparison
Section titled “Comparison”Comparison operators evaluate to a bool.
==(Equal),!=(Not equal)>(Greater than),<(Less than)>=(Greater than or equal),<=(Less than or equal)
var isEqual = (a == b);var isValid = (age >= 18);Logical
Section titled “Logical”Logical operators work with bool values and support short-circuit evaluation — the right operand is only evaluated when necessary.
&& — Logical AND
Section titled “&& — Logical AND”Returns true only if both operands are true. If the left operand is false, the right operand is not evaluated.
var canEnter = (hasTicket && isAdult);var safe = (ptr != null && ptr.value > 0); // short-circuits if ptr is null|| — Logical OR
Section titled “|| — Logical OR”Returns true if either operand is true. If the left operand is true, the right operand is not evaluated.
var allowed = (isAdmin || hasPermission);var fallback = (config != null || useDefaults());! — Logical NOT
Section titled “! — Logical NOT”Negates a boolean value.
var invert = !canEnter;var isEmpty = !list.length();Nullish Coalescing
Section titled “Nullish Coalescing”?? — Nullish Coalescing
Section titled “?? — Nullish Coalescing”The ?? operator returns the left operand if it is not null; otherwise it returns the right operand. Unlike ||, it only checks for null — not for false, 0, or empty strings.
var name = inputName ?? "Anonymous"; // "Anonymous" if inputName is nullvar port = configPort ?? 8080; // 8080 if configPort is nullUse ?? when you want to provide a default value for potentially null variables:
function greet(name: string?) { var displayName = name ?? "Guest"; println("Hello, " + displayName);}
greet("Alice"); // Hello, Alicegreet(null); // Hello, GuestIncrement / Decrement
Section titled “Increment / Decrement”These operators mutate the variable exactly by 1.
++(Increment by 1),--(Decrement by 1)
var i = 0;i++; // i is now 1Compound Assignment
Section titled “Compound Assignment”Compound assignment operators combine an arithmetic operation with assignment. The expression x op= y is equivalent to x = x op y.
| Operator | Name | Equivalent | Example |
|---|---|---|---|
+= | Add and assign | x = x + y | count += 1 |
-= | Subtract and assign | x = x - y | health -= damage |
*= | Multiply and assign | x = x * y | price *= quantity |
/= | Divide and assign | x = x / y | total /= numItems |
%= | Modulo and assign | x = x % y | index %= arrayLength |
var count: int = 10;count += 5; // 15 — equivalent to count = count + 5count -= 3; // 12count *= 2; // 24count /= 4; // 6count %= 4; // 2Compound assignments work with all numeric types (int, float) and += also works for string concatenation:
var greeting: string = "Hello";greeting += ", world!"; // "Hello, world!"
var total: float = 100.0;total *= 0.85; // Apply 15% discount → 85.0They are commonly used in loops:
var sum: int = 0;for (var i: int = 0; i < 100; i += 10) { sum += i;}println(sum); // 450Bitwise
Section titled “Bitwise”Bitwise operators work directly on the binary representation of integer values.
| Operator | Name | Description | Example |
|---|---|---|---|
& | AND | Sets each bit to 1 if both bits are 1 | 0xFF & 0x0F → 15 |
| | OR | Sets each bit to 1 if either bit is 1 | 0xF0 | 0x0F → 255 |
^ | XOR | Sets each bit to 1 if only one bit is 1 | 0xFF ^ 0x0F → 240 |
~ | NOT | Inverts all bits | ~0 → -1 |
<< | Left shift | Shifts bits left by n positions | 1 << 8 → 256 |
>> | Right shift | Shifts bits right by n positions | 256 >> 8 → 1 |
// Bitwise AND — mask the lower nibbleprintln(0xFF & 0x0F); // 15
// Bitwise OR — combine flagsprintln(0xF0 | 0x0F); // 255
// Bitwise XOR — toggle bitsprintln(0xFF ^ 0x0F); // 240
// Bitwise NOT — invert all bitsprintln(~0); // -1println(~255); // -256
// Shift operatorsprintln(1 << 4); // 16 (multiply by 2⁴)println(256 >> 4); // 16 (divide by 2⁴)println(0xFF << 8); // 65280Bitwise operators work with variables and can be combined:
var flags: int = 0xAB;var mask: int = 0x0F;
println(flags & mask); // 11 (lower nibble)println(flags | mask); // 175println(flags ^ mask); // 164println(flags >> 4); // 10 (upper nibble)println((0xFF & 0x0F) | 0xF0); // 255 (combined operations)println((1 << 8) - 1); // 255 (bitmask for 8 bits)Control Flow Expressions in Detail
Section titled “Control Flow Expressions in Detail”If Expression
Section titled “If Expression”The last expression in the matching branch is the value of the entire if expression:
var max = if (a > b) { a } else { b }Both branches should evaluate to the same type when used as a value.
While Expression
Section titled “While Expression”A while loop is also an expression. In practice, its value is the result of the last iteration (or null if the loop never executes):
var i = 0while (i < 10) { i++;}For Expression
Section titled “For Expression”Similarly, a for loop is an expression:
var sum = 0for (var i = 0; i < 5; i++) { sum += i;}For-of Expression
Section titled “For-of Expression”Iterates over elements of a collection:
const colors = ["red", "green", "blue"]for (color of colors) { println(color);}For-in Expression
Section titled “For-in Expression”Iterates over keys of a map:
const scores: map[string]int = {"math": 90, "science": 85}for (subject in scores) { println(subject + ": " + scores[subject]);}Why Expression-Based?
Section titled “Why Expression-Based?”The expression-based design offers several advantages:
- Fewer language constructs —
if/elseworks as an expression, and the ternary operator (? :) offers a concise alternative. - More concise code — Assign values directly from control flow without pre-declaring mutable variables.
- Consistency — Everything that evaluates logically has a value, making the language more uniform.
- Composability — Expressions can be nested and combined freely.
// Without expression-based design (imperative style):var result: string;if (x > 0) { result = "positive";} else { result = "negative";}
// With expression-based design (concise):var result: string = if (x > 0) { "positive" } else { "negative" };