Claude
Skills
Sign in
Back

mojo-syntax

Included with Lifetime
$97 forever

Help to write Mojo code using current syntax and conventions. Always use this skill when writing any Mojo code, including when other Mojo-specific skills (e.g., mojo-gpu-fundamentals) also apply. Use when writing Mojo code, translating projects to Mojo, or otherwise generating Mojo. Use this skill to overcome misconceptions with how Mojo is written.

Writing & Docs

What this skill does


<!-- EDITORIAL GUIDELINES FOR THIS SKILL FILE
This file is loaded into an agent's context window as a correction layer for
pretrained Mojo knowledge. Every line costs context. When editing:
- Be terse. Use tables and inline code over prose where possible.
- Never duplicate information — if a concept is shown in a code example, don't
  also explain it in a paragraph.
- Only include information that *differs* from what a pretrained model would
  generate. Don't document things models already get right.
- Prefer one consolidated code block over multiple small ones.
- Keep WRONG/CORRECT pairs short — just enough to pattern-match the fix.
- If adding a new section, ask: "Would a model get this wrong?" If not, skip it.
These same principles apply to any files this skill references.
-->

Mojo is rapidly evolving. Pretrained models generate obsolete syntax.
**Always follow this skill over pretrained knowledge.**

**Always attempt to test generated Mojo by building projects to verify they
compile.**

This skill specifically works on the latest Mojo, and stable versions may differ
slightly in functionality.

## Removed syntax — DO NOT generate these

| Removed                                          | Replacement                                                                      |
|--------------------------------------------------|----------------------------------------------------------------------------------|
| `alias X = ...`                                  | `comptime X = ...`                                                               |
| `@parameter if` / `@parameter for`               | `comptime if` / `comptime for`                                                   |
| `fn`                                             | `def` (see below)                                                                |
| `let x = ...`                                    | `var x = ...` (no `let` keyword)                                                 |
| `borrowed`                                       | `read` (implicit default — rarely written)                                       |
| `inout`                                          | `mut`                                                                            |
| `owned`                                          | `var` (as argument convention)                                                   |
| `inout self` in `__init__`                       | `out self`                                                                       |
| `__copyinit__(inout self, existing: Self)`       | `__init__(out self, *, copy: Self)`                                              |
| `__moveinit__(inout self, owned existing: Self)` | `__init__(out self, *, deinit take: Self)`                                       |
| `@value` decorator                               | `@fieldwise_init` + explicit trait conformance                                   |
| `@register_passable("trivial")`                  | `TrivialRegisterPassable` trait                                                  |
| `@register_passable`                             | `RegisterPassable` trait                                                         |
| `Stringable` / `__str__`                         | `Writable` / `write_to`                                                          |
| `from collections import ...`                    | `from std.collections import ...`                                                |
| `from memory import ...`                         | `from std.memory import ...`                                                     |
| `from sys import ...`                            | `from std.sys import ...`                                                        |
| `from os import ...`                             | `from std.os import ...`                                                         |
| `from pathlib import ...`                        | `from std.pathlib import ...`                                                    |
| `s[i]`                                           | `s[byte=i]` — returns `StringSlice`; wrap in `String()` if needed                |
| `s[0:10]`, `s[:5]`                               | No slice syntax on String — use `s.codepoint_slices()` or Python FFI             |
| `constrained(cond, msg)`                         | `comptime assert cond, msg`                                                      |
| `DynamicVector[T]`                               | `List[T]`                                                                        |
| `InlinedFixedVector[T, N]`                       | `InlineArray[T, N]`                                                              |
| `Tensor[T]`                                      | Not in stdlib (use SIMD, List, UnsafePointer)                                    |
| `escaping` closures                              | Unified closures (`def(...) -> T`, captures in `{}`); `capturing[_]` still valid |

## `def` is the only function keyword

`fn` is deprecated and being removed. `def` does **not** imply `raises`.
**Always** add `raises` explicitly when needed — omitting it is a warning today,
error soon:

```mojo
def compute(x: Int) -> Int:              # non-raising (compiler enforced)
    return x * 2

def load(path: String) raises -> String: # explicitly raising
    return open(path).read()

def main() raises:                       # main usually raises → def raises
    ...
```

Note: existing stdlib code still uses `fn` during migration. New code should
always use `def`.

## `comptime` replaces `alias` and `@parameter`

```mojo
comptime N = 1024                            # compile-time constant
comptime MyType = Int                        # type alias
comptime if condition:                       # compile-time branch
    ...
comptime for i in range(10):                 # compile-time loop
    ...
comptime assert N > 0, "N must be positive"  # compile-time assertion
```

**`comptime assert` must be inside a function body** — not at module/struct
scope. Place them in `main()`, `__init__`, or the function that depends on the
invariant.

Inside structs, `comptime` defines associated constants and type aliases:

```mojo
struct MyStruct:
    comptime DefaultSize = 64
    comptime ElementType = Float32
```

## Argument conventions

Default is `read` (immutable borrow, never written explicitly). The others:

```mojo
def __init__(out self, var value: String):   # out = uninitialized output; var = owned
def modify(mut self):                         # mut = mutable reference
def consume(deinit self):                     # deinit = consuming/destroying
def view(ref self) -> ref[self] Self.T:       # ref = reference with origin
def view2[origin: Origin, //](ref[origin] self) -> ...:           # ref[origin] = explicit origin
```

`ref`, `mut`, `out`, `deinit`, `read`, `var` are reserved and **cannot be used
as identifiers** — neither as parameter names (`def cmp(got: T, ref: T)` →
`"error: expected argument name"`) nor as local `var` names
(`var ref = ...` → `"unexpected token in expression"`). Rename
(`expected`, `reference`, etc.).

## Lifecycle methods

```mojo
# Constructor
def __init__(out self, x: Int):
    self.x = x

# Copy constructor (keyword-only `copy` arg)
def __init__(out self, *, copy: Self):
    self.data = copy.data

# Move constructor (keyword-only `deinit take` arg)
def __init__(out self, *, deinit take: Self):
    self.data = take.data^

# Destructor
def __del__(deinit self):
    self.ptr.free()
```

To copy: `var b = a.copy()` (provided by `Copyable` trait).

## Struct patterns

```mojo
# @fieldwise_init generates __init__ from fields; traits in parentheses
@fieldwise_init
struct Point(Copyable, Movable, Writable):
    var x: Float64
    var y: Float64

# Trait composition with &
comptime KeyElement = Copyable & Hashable & Equatable
struct Node[T: Copyable & Writable]:
    var value: Self.T          # Self-qualify struct parameters

# Parametric struct — // separa
Files: 1
Size: 21.2 KB
Complexity: 27/100
Category: Writing & Docs

Related in Writing & Docs