moonbit-practice
MoonBit Practice Guide
Best practices for AI when generating MoonBit code.
If you don't understand something here, use moonbit-docs skill to search the official documentation.
Guidelines
Code Navigation: Prefer moon ide over Read/Grep
In MoonBit projects, prefer moon ide commands over Read tool or grep.
# ❌ Avoid: Reading files directly
Read src/parser.mbt
# ✅ Recommended: Find definitions from symbols
moon ide peek-def Parser::parse
moon ide goto-definition -tags 'pub fn' -query 'parse'
# ❌ Avoid: Searching with grep
grep -r "fn parse" .
# ✅ Recommended: Semantic search
moon ide find-references parse
moon ide outline src/parser.mbt
Why:
moon ideprovides semantic search (distinguishes definitions from call sites)- grep picks up comments and strings
moon docquickly reveals APIs
Other Rules
- Use
moon doc '<Type>'to explore APIs before implementing - Check reference/configuration.md before editing moon.pkg.json / moon.mod.json
- Check reference/agents.md when updating CLAUDE.md
Common Pitfalls
- Don't use uppercase for variables/functions - compilation error
mutis only for reassignment, not field mutation - Array push doesn't need itreturnis unnecessary - last expression is the return value- Methods require
Type::prefix ++--not supported - usei = i + 1ori += 1- No
tryneeded for error propagation - automatic (unlike Swift) - No
awaitkeyword - just declare withasync fn - Prefer range for over C-style -
for i in 0..<n {...} - Legacy syntax:
function_name!(...)andfunction_name(...)?are deprecated
Common Syntax Mistakes by AI
Type Parameter Position
///| NG: fn identity[T] is old syntax
fn identity[T](val: T) -> T { val }
///| OK: Type parameter comes right after fn
fn[T] identity(val: T) -> T { val }
raise Syntax
///|
/// NG: -> T!Error was removed
fn parse(s: String) -> Int!Error { ... }
///|
/// OK: Use raise keyword
fn parse(s: String) -> Int raise Error { ... }
Int raise is shorthand for Int raise Error.
async fn implicitly raises by default; use noraise to enforce no errors.
Macro Calls
///|
/// NG: ! suffix was removed
assert_true!(true)
///|
/// OK
assert_true(true)
Multi-line Text
let text =
#|line 1
#|line 2
Comments and Block Separators
///| is a block separator. /// comments attach to the following ///| block.
///|
/// This function is foo
fn foo() -> Unit { ... }
///|
/// This function is bar
fn bar() -> Unit { ... }
Avoid consecutive ///| at the file beginning as they create separate blocks.
Snapshot Tests
moon test -u auto-updates content="" in inspect(val).
test "snapshot" {
inspect([1, 2, 3], content="") // auto-filled by moon test -u
}
After running:
test "snapshot" {
inspect([1, 2, 3], content="[1, 2, 3]")
}
Doc Tests
Available in .mbt.md files or ///| inline comments.
| Code Block | Behavior |
|---|---|
```mbt check |
Checked by LSP |
```mbt test |
Executed as test {...} |
```moonbit |
Display only (not executed) |
Example (inline comment):
///|
/// Increment an integer by 1
/// ```mbt test
/// inspect(incr(41), content="42")
/// ```
pub fn incr(x : Int) -> Int {
x + 1
}
Pre-release Checklist
Run before releasing:
moon fmt # Format code
moon info # Generate type definition files
pkg.generated.mbti is auto-generated by moon info. Don't edit it directly.
Exploring Built-in Type Methods
moon doc StringView # StringView methods
moon doc Array # Array methods
moon doc Map # Map methods
Quick Reference
| Topic | Command | Details |
|---|---|---|
| Test | moon test |
https://docs.moonbitlang.com/en/stable/language/tests |
| Update snapshots | moon test -u |
Same as above |
| Filtered test | moon test --filter 'glob' |
Run specific tests |
| Benchmark | moon bench |
https://docs.moonbitlang.com/en/stable/language/benchmarks |
| Doc Test | moon check / moon test |
https://docs.moonbitlang.com/en/stable/language/docs |
| Format | moon fmt |
- |
| Generate types | moon info |
- |
| Doc reference | moon doc <Type> |
- |
moon ide Tools
More accurate than grep for code navigation. See reference/ide.md for details.
# Show symbol definition
moon ide peek-def Parser::read_u32_leb128
# Package outline
moon ide outline .
# Find references
moon ide find-references TranslationUnit
# Jump to type definition (with location)
moon ide peek-def Parser -loc src/parse.mbt:46:4
Functional for loop
Prefer functional for loops whenever possible. More readable and easier to reason about.
// Functional for loop with state
for i = 0, sum = 0; i <= 10; {
continue i + 1, sum + i // Update state
} else {
sum // Value at loop exit
}
// Range for (recommended)
for i in 0..<n { ... }
for i, v in array { ... } // index and value
Error Handling
MoonBit uses checked errors. See reference/ffi.md for details.
///| Declare error type
suberror ParseError {
InvalidEof
InvalidChar(Char)
}
///| Declare with raise, auto-propagates
fn parse(s: String) -> Int raise ParseError {
if s.is_empty() { raise ParseError::InvalidEof }
...
}
///| Convert to Result
let result : Result[Int, ParseError] = try? parse(s)
///| Handle with try-catch
parse(s) catch {
ParseError::InvalidEof => -1
_ => 0
}
Assets
assets/ci.yaml is a GitHub Actions workflow for CI