This document contains essential MoonBit knowledge that LLMs cannot know without external environment access. Last updated: December 2024.
Current Status: Beta (as of December 2024)
- Version 1.0 planned for 2026
- Core language features are now stable
- Breaking changes will follow RFC process
# Create new project
moon new project-name
# Generated structure:
project-name/
├── moon.mod.json # Project manifest
├── lib/ # Library package
│ ├── moon.pkg.json # Package config
│ ├── lib.mbt # Implementation
│ └── lib_test.mbt # Tests
└── main/ # Main package
├── moon.pkg.json
└── main.mbt # Entry point{
"name": "username/project-name",
"version": "0.1.0",
"deps": {},
"readme": "README.md",
"repository": "https://github.com/username/project-name",
"license": "MIT"
}{
"import": ["lib"],
"test_import": ["@test"]
}# Project management
moon new <name> # Create new project
moon init # Initialize in existing directory
moon version # Show moon version
# Development
moon check # Type check only
moon build # Build project
moon run main [args] # Run main package
moon test # Run all tests
moon clean # Clean build artifacts
# Package management
moon add <package> # Add dependency
moon remove <package> # Remove dependency
moon update # Update dependencies
moon publish # Publish to mooncakes.io
# Documentation
moon doc # Generate documentation
moon info # Show project info
# Formatting
moon fmt # Format code
moon fmt --check # Check formatting
# Coverage
moon test --coverage # Run tests with coverage
moon coverage report # Show coverage report.mbt- MoonBit source files.mbt.md- Markdown-oriented programming files (new feature)_test.mbt- Test files.mbti- Interface files (for virtual packages)
// Import from standard library
fn main {
let list = @list.of([1, 2, 3])
let map = @map.Map::new()
println(@json.stringify(data))
}
// Import from local package
// If lib package exports process_data function
fn main {
let result = @lib.process_data(input)
}
// No explicit import statements - use @ prefix// Core types
@int, @int64, @uint, @uint64
@double, @float
@string, @char, @byte, @bytes
@bool, @unit
// Collections
@array.Array[T]
@list.List[T]
@map.Map[K, V]
@hashmap.HashMap[K, V]
@set.Set[T]
@queue.Queue[T]
// Utilities
@option.Option[T]
@result.Result[T, E]
@ref.Ref[T]
@lazy.Lazy[T]
// I/O and System
@io
@fs
@env
@time
// Serialization
@json
@serde
// Testing
@test
@assertion
// Math
@math
@random
// Algorithms
@sort
@searchlet name = "Alice"
let age = 30
println("Hello, \{name}! You are \{age} years old.")
// Note: Uses \{} not ${} or {}// Array literal
let arr = [1, 2, 3, 4, 5]
// Array methods
arr.push(6)
arr.pop()
arr.length()
arr.map(fn(x) { x * 2 })
arr.filter(fn(x) { x % 2 == 0 })
arr.fold(0, fn(acc, x) { acc + x })// Must be exhaustive
match value {
Some(x) => x
None => 0
}
// Guard clauses
match x {
n if n > 0 => "positive"
0 => "zero"
_ => "negative"
}// Option
let value = some_option.or(default_value)
let mapped = some_option.map(fn(x) { x + 1 })
// Result
let result = operation()
.map_err(fn(e) { "Error: " + e.to_string() })
.and_then(fn(x) { another_operation(x) })type Person { name: String; age: Int }
let p1 = { name: "Alice", age: 30 }
let p2 = { ..p1, age: 31 } // Spread syntax// Methods use :: syntax
fn Array::sum(self : Array[Int]) -> Int {
self.fold(0, fn(acc, x) { acc + x })
}
// Call with dot notation
let total = [1, 2, 3].sum()async fn fetch_data() -> String! {
let response = http_get!(url) // Note: ! suffix for async calls
response.text!()
}
// No await keyword neededfn sort[T : Compare](arr : Array[T]) -> Array[T] {
// T must implement Compare trait
}
fn debug[T : Show + Eq](value : T) {
// Multiple constraints with +
}// Error
let empty = []
// Fix
let empty : Array[Int] = []// Error
let x = 5
x = 6
// Fix
let mut x = 5
x = 6// Error
match option {
Some(x) => x
// Missing None case
}
// Fix
match option {
Some(x) => x
None => default
}// Error in moon.pkg.json
{
"import": ["nonexistent"]
}
// Fix: Add to moon.mod.json deps first
{
"deps": {
"package-name": "0.1.0"
}
}moon build --target wasm
# Outputs to target/wasm/release/build/main/main.wasm// Export to JavaScript
pub fn add(a : Int, b : Int) -> Int {
a + b
}
// Use extern for importing
extern fn console_log(s : String) = "console" "log"moon build --target wasm --release # Optimized build
moon build --target wasm -g # Debug buildtest "addition works" {
assert_eq(1 + 1, 2)
assert_ne(1 + 1, 3)
assert(1 < 2, "1 should be less than 2")
}test "error handling" {
match risky_operation() {
Ok(value) => assert_eq(value, expected)
Err(e) => assert(false, "Should not error: \{e}")
}
}test "reverse twice equals original" {
@quickcheck.check(fn(arr : Array[Int]) {
arr.reverse().reverse() == arr
})
}# 1. Update moon.mod.json with your username
{
"name": "yourusername/package-name",
"version": "0.1.0"
}
# 2. Login (first time)
moon login
# 3. Publish
moon publish// moon.mod.json
{
"deps": {
"username/package": "0.1.0"
}
}// virtual-pkg/moon.pkg.json
{
"virtual": true,
"has-default": true
}// logger.mbti
fn log(String) -> Unit
fn error(String) -> Unit// main/moon.pkg.json
{
"import": ["virtual-logger"],
"overrides": {
"virtual-logger": "my-logger-impl"
}
}wasm- WebAssembly (default)wasm-gc- WebAssembly with GC proposaljs- JavaScript (ES6+)native- Native code via LLVMriscv- RISC-V assembly
// Access command line arguments
let args = @env.get_args()
// Note: Full environment variable access may be limited
// depending on target platform-
Arrays are mutable and efficient
- Random access: O(1)
- Append: O(1) amortized
-
Prefer iterators over intermediate arrays
// Good arr.filter(pred).map(transform).fold(init, combine) // Better (if available) arr.filter_map(fn(x) { ... })
-
String concatenation
// Inefficient for many concatenations let s = s1 + s2 + s3 + s4 // Better: Use StringBuilder when available let sb = @string.StringBuilder::new() sb.append(s1) sb.append(s2) sb.to_string()
println("Debug: \{variable}")
debug(value) // Pretty-prints complex typesassert(condition, "Error message")
debug_assert(condition) // Only in debug builds- Forgetting mut for mutable variables
- Not handling all enum cases in match
- Type inference limitations with empty collections
- Async function calls need ! suffix
- No null/nil - use Option[T]
- Strings are immutable
- No implicit type conversions
- Official extension: "MoonBit"
- Features: syntax highlighting, code completion, inline errors, formatting
moon lsp # Start language server- Markdown-oriented programming (.mbt.md files)
- Virtual packages for dependency injection
- Async/await with ! syntax (experimental)
- Native backend via LLVM
- Open-sourced compiler
- Python interop (in development)
This document should be updated as MoonBit evolves. Check official sources for the latest information.