> For the complete Mojo documentation index, see [llms.txt](/llms.txt).
> Markdown versions of all pages are available by appending .md to any URL (e.g. /docs/manual/basics.md).

# Mojo expression reference

<!-- VERIFIED: ParserExprs.cpp, ExprNode.h, ParserBase.h,
     ExprNodes.h -->

An *expression* is any piece of code that produces a value.
Expressions are the building blocks of computation: you combine
them with operators, pass them as arguments, assign their
results to variables, and use them as conditions in control
flow.

## Identifier expressions

An identifier refers to a named element: a variable, function,
type, or module. Using an identifier in an expression gives you
the thing it refers to:

```mojo
score        # a variable
Int          # a type
range        # a function
```

## Parenthesized expressions

Parentheses group subexpressions, overriding default
precedence:

```mojo
(a + b) * c  # add a and b, multiply by c
(x)          # just x
```

Parentheses also let expressions span multiple lines without
using backslash escapes:

```mojo
var result = (
    first_value
    + second_value
    + third_value
)
```

## Tuples

A *tuple* is a fixed-size, ordered group of values. The comma
is what creates a tuple, not the parentheses:

```mojo
var a = 2, 3       # tuple without parentheses
var b = (2, 3)     # same tuple with parentheses
var x, y = b       # x is 2, y is 3
```

Use a trailing comma to create a one-element tuple. Without it,
`(1)` is just the integer `1` in parentheses:

```mojo
()          # empty tuple
(1,)        # one-element tuple
(1, 2, 3)   # three-element tuple
```

Tuples support indexing:

```mojo
var point = (10, 20)
print(point[0])  # 10
```

## Collection displays

The compiler calls these *displays*. Displays are similar to
literals, but unlike literals, displays can contain expressions
as well as fixed values.

### Lists

A *list display* creates a list from comma-separated values:

```mojo
var empty = []
var numbers = [1, 2, 3]
var mixed = [1, "two", 3.0,]
```

Mojo allows trailing commas after all collection elements,
including the final one.

### Dictionaries

A *dict display* maps keys to values with `:` between each
pair:

```mojo
var empty = {}
var ages = {"Alice": 30, "Bob": 25}
```

### Sets

A *set display* uses braces with values but no colons:

```mojo
var primes = {2, 3, 5, 7}
```

Don't mix set and dict syntax. `{1, 2}` is a set. `{1: 2}` is a dict.

```mojo
{"a": 1, 2}   # Error: cannot mix 'key: value' pairs and set elements
{1, "b": 2}   # Error: cannot mix 'key: value' pairs and set elements
```

Brace syntax also serves as an *initializer list* that creates
an instance of an inferred type. Without type context, the
compiler can't distinguish a set from an initializer list, so
the distinction is resolved at type-check time. Initializer
lists can include positional values and keyword arguments:

```mojo
{x, y}           # set or initializer list, without context
{z=4, "foo"}     # initializer list with keyword argument
```

Initializer lists are syntactic sugar for constructor calls.
`{1, "hello"}` is equivalent to `T(1, "hello")` when the
type `T` is known from context. Use them for passing
initialized instances as arguments:

```mojo
process({1, "hello"})  # type inferred from signature
```

## Member access

The dot operator accesses an attribute or method on a value:

```mojo
var length = text.count()
var x = point.x
var name = person.name.upper()
```

Chaining is left to right: `a.b.c` accesses `c` on the
result of `a.b`.

## Calls

A *call expression* invokes a function or constructs a value
by appending `()` to an expression:

```mojo
print("hello")
var result = compute(a, b)
var p = Point(1.0, 2.0)
```

### Positional and keyword arguments

Arguments before any keyword argument are positional. Keyword
arguments use `name=value` syntax.

```mojo
def greet(name: String, loud: Bool = False):
    print(t"Hello, {name if not loud else name.upper()}!")

greet("Alice")  # Hello, Alice!
greet("Alice", loud=True)  # Hello, ALICE!
greet(name="Bob") # Hello, Bob!
```

Positional arguments can't follow keyword arguments:

```mojo
    # greet(loud=True, "Alice")
    # Error: positional argument follows keyword argument
```

Keyword arguments can't be repeated:

```mojo
greet(name="Alice", name="Bob")
# Error: duplicate keyword argument 'name'
```

## Subscripts and slices

Square brackets after an expression look up a value by
index(es) or key(s):

```mojo
var item = collection[0]
var value = mapping["key"]
var cell = matrix[i, j]
```

### Slices

Colons inside square brackets create *slices*. Slices select
a range of elements using `start:stop` or
`start:stop:stride`:

```mojo
var items = [0, 1, 2, 3, 4, 5]

var first_three = items[0:3]   # [0, 1, 2] (3 not included)
var from_three  = items[3:]    # [3, 4, 5]
var every_other = items[::2]   # [0, 2, 4]
var reversed    = items[::-1]  # [5, 4, 3, 2, 1, 0]
```

All three parts are optional. Start defaults to the beginning,
stop defaults to the end, and stride defaults to 1. The
element at the stop position isn't included in the result.

## Ternary conditional

The `if`-`else` expression selects between two values based
on a condition:

```mojo
var label = "even" if x % 2 == 0 else "odd"
```

The condition follows `if`, and the alternate value follows
`else`. If the condition is true, the expression evaluates to
the first value. If false, the alternate.

Ternary expressions are right-associative and can be chained:

```mojo
var size = (
    "small" if n < 10
        else "large" if n > 100
        else "medium"
)
```

This groups as
`"small" if n < 10 else ("large" if n > 100 else "medium")`.

## Walrus operator

Regular assignment (`=`) is a statement. It can't appear inside a larger
expression. The walrus operator (also known as the assignment expression)
`:=` is the expression form of assignment: it binds a value to a name and
evaluates to that same value, so the result can be used immediately:

```mojo
if (n := len(items)) > 10:
    print(n)

while (name := input("Prompt: ")) != "quit":
    print(name)
```

The walrus operator implicitly declares the variable in `def` methods and
functions. It has the lowest precedence of any expression operator, so
parentheses are typically needed when used inside larger expressions.

```mojo
# Walrus requires a function scope
n := len(items)      # Error: expressions must be inside a function

# Walrus is not valid inside subscripts
def main():
    items = [1, 2, 3]
    items[n := 2]    # Error: walrus is not allowed in subscripts
```

## Compile-time expressions

`comptime` forces an expression to evaluate at compile time.
Parentheses are required:

```mojo
def heavy_calculation() -> Int:
    var sum = 0
    for i in range(1_000_000):
        sum += i
    return sum

# var x = comptime heavy_calculation()
# Error: requires parentheses

var x = comptime(heavy_calculation())  # O(1) at runtime
print(x)  # 499999500000
```

The loop runs once during compilation. At runtime, `x` is
a constant. If the expression can't be evaluated at compile
time, the compiler reports an error.

Mojo also provides built-in expressions for compile-time
type introspection. These look like function calls but
they're keywords that operate on types and traits at
compile time:

```mojo
type_of(x)             # type of an expression
conforms_to(T, Trait)  # test trait conformance
origin_of(x)           # origin of a reference
```

These three expressions don't work the way most people
expect. They're used for reflection, conditional type
conformance, and origin sets. They return compiler-internal
types and won't print.

<!-- TODO: Uncomment when closure design stabilizes.
## Function type expressions

A function type expression describes the signature of a
function as a type:

```mojo
def() -> Int
def(Int, Int) -> Int
def(var value: String) -> None
def() raises -> String
```

Function type expressions can include argument types with
conventions, return types, and effects like `raises`.
-->

## Comprehension expressions

A comprehension is a concise way to build a new collection by
iterating over existing values and optionally filtering or
transforming them. It replaces common loop-and-append patterns
with a single, (usually) readable expression.

### List comprehensions

List comprehensions create lists:

```mojo
var squares = [x * x for x in [0, 1, 2, 3, 4] if x % 2 == 0]
# [0, 4, 16]

var positive = [x for x in range(-3, 3) if x > 0]
# [1, 2]
```

**Syntax:** `[expr for pattern in iterable if condition]`

- Multiple `for` clauses create nested iteration
- `if` clauses filter elements

### Set comprehensions

Set comprehensions create sets. Sets don't store duplicates,
so you may get fewer elements than iterations:

```mojo
var fibs = {fib(x) for x in range(6)}
# {1, 2, 3, 5, 8}, 5 elements from 6 iterations
```

**Syntax:** `{expr for pattern in iterable if condition}`

### Dictionary comprehensions

Dictionary comprehensions create dictionaries:

```mojo
var dict_squares = {x: x * x for x in range(3)}
# {0: 0, 1: 1, 2: 4}

var lengths: Dict[String, Int] = {
    k: len(k) for k in ["one", "two", "three", "four"]
}
# {one: 3, two: 3, three: 5, four: 4}
```

**Syntax:**
`{key_expr: value_expr for pattern in iterable if condition}`

### Comprehension clauses

Comprehensions support multiple `for` and `if` clauses:

```mojo
var products = [
    (x, y, x * y)
    for x in range(3)
    for y in range(3)
    if (x + y) % 2 == 0
]
# [(0, 0, 0), (0, 2, 0), (1, 1, 1), (2, 0, 0), (2, 2, 4)]
```

Clauses are evaluated left to right:

- Each `for` introduces a new iteration variable
- Each `if` filters based on the current values
