This tutorial is a compact, linear introduction to Nex in small steps, with complete examples.
Unless noted otherwise, snippets are REPL-friendly fragments.
Nex programs are built from class declarations, function declarations, and calls.
print("Hello, Nex")
Comments start with --:
-- This line is ignored by the compiler/interpreter
print("Hello again")
Variables are introduced with let and assigned with
:=.
let name: String := "Ada"
let age: Integer := 12
let height: Real := 1.52
let ok: Boolean := true
In the REPL, type annotations are optional by default:
let x := 10
let y := x + 5
Built-in scalar types include:
IntegerInteger64RealDecimalCharBooleanStringDetachable (nullable) types use a leading ?:
let maybe_name: ?String := nil
Arithmetic:
let a := 10 + 2 * 3
let b := (10 + 2) * 3
let c := 10 % 3
let d := 2 ^ 8
Comparison and boolean logic:
let e := a = b
let f := a /= b
let g := (a > 5) and (b < 40)
let h := not g
Operator precedence follows conventional order: unary,
multiplicative, additive, comparison, equality, and,
or.
if age >= 18 then
print("adult")
elseif age >= 13 then
print("teen")
else
print("child")
end
when is an expression, so it can appear on the
right-hand side:
let category := when age >= 18 "adult" else "minor" end
case age of
0, 1, 2 then print("small")
3, 4, 5 then print("medium")
else print("large")
end
Each then branch takes a statement. If you need multiple
statements, use a scoped do ... end block.
from ... until ... do ... endfrom
let i: Integer := 1
until
i > 5
do
print(i)
i := i + 1
end
repeatrepeat 3 do
print("tick")
end
acrossacross [10, 20, 30] as x do
print(x)
end
across also works with strings and maps.
Top-level functions use function:
function greet(name: String)
do
print("Hello, " + name)
end
function double(n: Integer): Integer
do
result := n * 2
end
Call forms:
greet("Bob")
print(double(5))
Anonymous functions use fn:
let inc := fn (n: Integer): Integer do
result := n + 1
end
print(inc(10))
let xs: Array [Integer] := [1, 2, 3]
print(xs.get(0))
let m: Map [String, String] := {"name": "Nex", "kind": "language"}
print(m.get("name"))
Array and map literals are expressions, so they can be nested.
A class groups fields and methods.
class Counter
create
make(start: Integer) do
this.value := start
end
feature
value: Integer
inc() do
this.value := this.value + 1
end
current(): Integer do
result := value
end
end
Construction uses create:
let c: Counter := create Counter.make(10)
c.inc
print(c.current)
Parameterless calls may omit parentheses (c.inc,
c.current).
class Box [T]
create
make(initial: T) do
this.value := initial
end
feature
value: T
get(): T do
result := value
end
end
With constraints:
class Dictionary [K -> Hashable, V]
feature
key: K
value: V
end
class Animal
feature
name: String
speak do
print(name)
end
create
named(name: String) do
this.name := name
end
end
class Dog
inherit Animal
feature
speak do
print(name + " says woof")
end
end
let a: A := create Animal.named("Ko")
a.speak -- "Ko"
let d: A := create Dog.named("Ki")
d.speak -- "Ki says woof"
Nex also supports adaptation in inheritance (rename,
redefine) for precise reuse.
Contracts are first-class in Nex.
class Wallet
feature
money: Real
spend(amount: Real)
require
non_negative_amount: amount >= 0.0
enough: amount <= money
do
this.money := money - amount
ensure
decreased: money = old money - amount
end
create
with_balance(amount: Real) do
money := amount
end
invariant
never_negative: money >= 0.0
end
let w: Wallet := create Wallet.with_balance(-10)
Error: Class invariant violation: never_negative
## 12. Debugger Quickstart
Enable debugger in REPL:
```text
:debug on
Set breakpoints and run:
:break Wallet.spend
:break Wallet.spend if amount > 100
:break field:money
:tbreak Wallet.spend:42
At dbg> prompt:
:where
:locals
:print money
:next
:continue
Watch values change:
:watch money
:watch money if money > 100
:watches
Tune breakpoint hit behavior:
:ignore 1 2 -- breakpoint[1] ignores first 2 hits
:every 1 3 -- breakpoint[1] pauses every 3rd hit
Control breakpoints without deleting:
:disable 1
:enable 1
Pause on failures:
:breakon exception on
:breakon contract on
:breakon contract filter invariant
Save and restore debugger state:
:breaksave .nex-debug.edn
:breakload .nex-debug.edn
Script debugger commands from a file:
:debugscript debug_commands.dbg
For full command reference, see docs/md/DEBUGGER.md.
let w: Wallet := create Wallet.with_balance(10.2) w.spend(9) w.money – 1.1999999999999993 w.spend(2) – Error: Precondition violation: enough
Use contracts to state assumptions (`require`), guarantees (`ensure`), and global consistency rules (`invariant`).
## 12. Errors and Recovery
```nex
let attempts := 0
do
attempts := attempts + 1
if attempts < 3 then
raise "not ready"
end
print("ok")
rescue
print("retrying")
retry
end
raise, rescue, and retry
provide structured recovery paths.
import java.util.Scanner
import Math from './math.js'
intern math/Calculator
intern math/Calculator as Calc
Use intern for Nex-to-Nex modularity and
import for target-platform interop.
class BankAccount
create
make(initial: Real) do
this.balance := initial
end
feature
balance: Real
deposit(amount: Real)
require
positive: amount > 0.0
do
this.balance := balance + amount
ensure
grew: balance >= old balance
end
withdraw(amount: Real)
require
positive: amount > 0.0
enough: amount <= balance
do
this.balance := balance - amount
ensure
shrank: balance = old balance - amount
end
show do
print("balance = " + balance)
end
invariant
never_negative: balance >= 0.0
end
let account := create BankAccount.make(100.0)
account.deposit(25.0)
account.withdraw(40.0)
account.show
intern (Section 13).max(a, b: Integer): Integer using
if.10 down to
1.Pair [A, B] class with
first and second.transfer(amount) method between two
accounts.intern.