Mesh

Syntax Cheatsheet

A quick reference for Mesh syntax. For details, see the full guides linked in each section.

Basics

SyntaxExample
Variable bindinglet x = 42
Type annotationx :: Int
String interpolation"Hello, #{name}!" or "Hello, ${name}!"
Heredoc string"""multiline #{expr} content"""
Comment# this is a comment
Printprintln("hello")

Types

TypeExample
Int42, 0, -5
Float3.14, 0.5
String"hello", "#{x}"
Booltrue, false
List<T>[1, 2, 3]
Map<K, V>%{"key" => "value"}
Option<T>Some(42), None (shorthand: Int?)
Result<T, E>Ok(42), Err("fail") (shorthand: Int!String)
Fun(A) -> BFun(Int) -> String

String Features

mesh
# Hash-brace interpolation (v12.0, preferred)
let name = "World"
println("Hello, #{name}!")
println("Expr: #{count * 2 + 1}")

# Dollar-brace interpolation (also valid)
println("Hello, ${name}!")

# Heredoc strings (multiline, no escaping needed)
let body = """
  SELECT * FROM events WHERE id = #{id}
  """

# JSON object literals (prefer over heredoc JSON templates)
let resp = json { status: "ok", count: n }          # {"status":"ok","count":42}
let err  = json { error: reason }                    # {"error":"not found"}
let nest = json { result: json { code: 200 } }       # {"result":{"code":200}}
HTTP.response(200, json { status: "ok", id: id })   # use directly as String

# Regex literals
let rx = ~r/\d+/
let rx_flags = ~r/[a-z]+/i     # i, m, s flags
let matched = Regex.is_match(rx, "hello123")

# Environment variables
let host = Env.get("HOST", "localhost")
let port = Env.get_int("PORT", 8080)

See Language Basics for details.

Functions

mesh
# Named function with types
fn add(a :: Int, b :: Int) -> Int do
  a + b
end

# Multi-clause (pattern matching)
fn fib(0) = 0
fn fib(1) = 1
fn fib(n) = fib(n - 1) + fib(n - 2)

# Guards
fn abs(n) when n < 0 = -n
fn abs(n) = n

# Anonymous function (closure)
let double = fn(x :: Int) -> x * 2 end

# Pipe operator
let result = 5 |> double |> add_one

# Slot pipe: route value to argument position N
let result = 10 |2> add(1)   # = add(1, 10) = 11

# Multi-line pipe: trailing form (|> at end of line)
let result = 5 |>
  double |>
  add_one

# Multi-line pipe: leading form (|> at start of next line)
let result = value
  |> transform
  |> process

# Useful for long chains (e.g. HTTP router setup)
let router = HTTP.router()
  |> HTTP.on_post("/events", handle_event)
  |> HTTP.on_get("/issues", handle_issues)

Both trailing and leading forms produce identical output to their single-line equivalents -- only formatting differs. See Language Basics for details.

Control Flow

mesh
# If/else
if x > 0 do
  "positive"
else
  "non-positive"
end

# Case (pattern matching)
case x do
  0 -> "zero"
  1 -> "one"
  _ -> "other"
end

# For loop (list comprehension)
let doubled = for x in [1, 2, 3] do
  x * 2
end

# For with range
for i in 0..5 do
  println("#{i}")
end

# While loop
while condition do
  # body
  break
end

Structs & Types

mesh
# Struct definition
struct Point do
  x :: Int
  y :: Int
end deriving(Eq, Display)

# Struct creation
let p = Point { x: 1, y: 2 }

# Sum type
type Color do
  Red
  Green
  Blue
end deriving(Eq, Display)

# Type alias (transparent -- alias and aliased type are interchangeable)
type Url = String
type Count = Int

# Exported type alias (importable by other modules)
pub type UserId = Int

# Cross-module import of a type alias
from Types.User import UserId
fn get_user(id :: UserId) -> String do
  String.from(id)
end

Type aliases are transparent -- a UserId value works wherever Int is valid (and vice versa), with no conversion needed. See Type System for details.

Interfaces & Traits

mesh
# Define a custom interface
interface Greeter do
  fn greet(self) -> String
end

# Implement for a type
impl Greeter for Person do
  fn greet(self) -> String do
    "Hello"
  end
end

# Associated types
interface Container do
  type Item
  fn first(self) -> Self.Item
end

impl Container for MyBox do
  type Item = Int
  fn first(self) -> Int do self.value end
end

# Deriving built-in traits
struct Tag do
  id :: Int
end deriving(Eq, Hash)

# Available derives: Eq, Ord, Display, Debug, Hash, Json

See Type System -- Traits for details.

Numeric Traits

mesh
# Operator overloading via traits
impl Add for Vec2 do
  type Output = Vec2
  fn add(self, other :: Vec2) -> Vec2 do
    Vec2 { x: self.x + other.x, y: self.y + other.y }
  end
end

# Available: Add (+), Sub (-), Mul (*), Div (/), Neg (unary -)
let sum = v1 + v2     # calls Add.add
let neg = -v1         # calls Neg.neg

See Type System -- Numeric Traits for details.

From/Into Conversion

mesh
# User-defined conversion
impl From<Int> for Wrapper do
  fn from(n :: Int) -> Wrapper do
    Wrapper { value: n }
  end
end
let w = Wrapper.from(42)

# Built-in conversions
let f = Float.from(42)       # Int -> Float
let s = String.from(42)      # Int -> String

# ? operator auto-converts error types via From
fn process() -> Int!AppError do
  let n = risky()?  # String error auto-converts to AppError
  Ok(n)
end

See Type System -- From/Into for details.

Iterators

mesh
# Create iterator from collection
let iter = Iter.from([1, 2, 3, 4, 5])

# Lazy combinators (chained with pipe operator)
Iter.from(list) |> Iter.map(fn x -> x * 2 end)
Iter.from(list) |> Iter.filter(fn x -> x > 3 end)
Iter.from(list) |> Iter.take(3)
Iter.from(list) |> Iter.skip(2)
Iter.from(list) |> Iter.enumerate()
Iter.from(a) |> Iter.zip(Iter.from(b))

# Terminal operations
Iter.from(list) |> Iter.count()
Iter.from(list) |> Iter.sum()
Iter.from(list) |> Iter.any(fn x -> x > 3 end)
Iter.from(list) |> Iter.all(fn x -> x > 0 end)
Iter.from(list) |> Iter.reduce(0, fn acc, x -> acc + x end)

# Collect into collections
Iter.from(list) |> Iter.map(fn x -> x * 2 end) |> List.collect()
Iter.from(list) |> Iter.enumerate() |> Map.collect()
Iter.from(list) |> Set.collect()
Iter.from(strings) |> String.collect()

See Iterators for details.

Error Handling

mesh
# Option type (T?)
fn find(x :: Int) -> Int? do
  if x > 0 do
    return Some(x)
  end
  None
end

# Result type (T!E)
fn divide(a :: Int, b :: Int) -> Int!String do
  if b == 0 do
    return Err("division by zero")
  end
  Ok(a / b)
end

# Early return with ?
fn compute(x :: Int) -> Int!String do
  let result = divide(x, 2)?
  Ok(result + 10)
end

Concurrency

mesh
# Actor definition
actor worker() do
  receive do
    msg -> println("got: #{msg}")
  end
end

# Spawn and send
let pid = spawn(worker)
send(pid, "hello")

# Supervisor
supervisor MySup do
  strategy: one_for_one
  max_restarts: 3
  max_seconds: 5

  child w do
    start: fn -> spawn(worker) end
    restart: permanent
    shutdown: 5000
  end
end

# Service (GenServer)
service Counter do
  fn init(n :: Int) -> Int do n end
  call Get() :: Int do |s| (s, s) end
  cast Reset() do |_s| 0 end
end

let pid = Counter.start(0)
Counter.get(pid)
Counter.reset(pid)

See Concurrency for details.

Modules

mesh
# Import a module
import String

# Use qualified access
let n = String.length("test")

# Import specific functions
from String import length
let n = length("test")

Operators

CategoryOperators
Arithmetic+, -, *, /, %
Comparison==, !=, <, >, <=, >=
Logicaland, or, not
Pipe|>
Slot pipe|N> (e.g. |2>)
String concat<>
List concat++
Error propagation?
Range..

Testing

mesh
# File: my_module.test.mpl
# Run with: meshc test my_app

test("basic assertions") do
  assert(1 + 1 == 2)
  assert_eq(10, 5 + 5)
  assert_ne(3, 4)
  assert_raises fn() do
    panic("boom")
  end
end

describe("grouped tests") do
  setup do
    assert(true)   # runs before each test
  end

  teardown do
    assert(true)   # runs after each test
  end

  test("inner test") do
    assert(true)
  end
end

test("actor messaging") do
  let me = self()
  send(me, 42)
  assert_receive 42, 500   # pattern, timeout_ms
end

# Mock actor for concurrency tests
let mock = Test.mock_actor(fn msg do
  # handle msg
  "ok"   # return "ok" to continue, "stop" to terminate
end)
AssertionDescription
assert exprFail if expr is false
assert_eq a, bFail if a != b
assert_ne a, bFail if a == b
assert_raises fnFail if fn does not raise
assert_receive pat, msFail if not received within timeout

See Testing for full guide.

Standard Library

mesh
# Crypto
let h256 = Crypto.sha256("hello")
let h512 = Crypto.sha512("hello")
let mac = Crypto.hmac_sha256("key", "msg")
let ok = Crypto.secure_compare("a", "a")   # Bool, constant-time
let id = Crypto.uuid4()                    # UUID v4 string

# Encoding
let b64 = Base64.encode("hello")
case Base64.decode(b64) do
  Ok(s) -> println(s)
  Err(e) -> println(e)
end
let url = Base64.encode_url("hello")

let hex = Hex.encode("hi")   # "6869"
case Hex.decode(hex) do
  Ok(s) -> println(s)
  Err(e) -> println(e)
end

# DateTime
let dt = DateTime.utc_now()
let iso = DateTime.to_iso8601(dt)
let ms = DateTime.to_unix_ms(dt)
case DateTime.from_iso8601("2024-01-15T10:30:00Z") do
  Ok(dt2) ->
    let next = DateTime.add(dt2, 7, :day)
    let diff = DateTime.diff(next, dt2, :day)   # Float
    let before = DateTime.is_before(dt2, next)  # Bool
    let after = DateTime.is_after(next, dt2)    # Bool
  Err(e) -> println(e)
end

See Standard Library for full reference.

Edit this page on GitHub
v14.0 Last updated: April 3, 2026