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
@search
let 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 needed
fn 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 build
test "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 types
assert(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.