Nex Syntax Postcards

Nex Syntax on a Postcard

Comments

-- This is a comment. The computer ignores it.
-- Use comments to explain your code to other humans!

Values and Variables

let name: String := "Alice"      -- a piece of text (String)
let age: Integer := 10           -- a whole number (Integer)
let height: Real := 4.5          -- a decimal number (Real)
let likes_cats: Boolean := true  -- true or false (Boolean)

Printing

print("Hello, world!")
print(name)
print("I am " + age + " years old")

Math

let sum: Integer := 3 + 4       -- 7
let diff: Integer := 10 - 3     -- 7
let product: Integer := 5 * 6   -- 30
let quotient: Integer := 20 / 4 -- 5
let remainder: Integer := 10 % 3 -- 1
let power: Integer := 2 ^ 8     -- 256

Comparing Things

x = y                            -- equal?
x /= y                           -- not equal?
x < y    x <= y                  -- less than? less or equal?
x > y    x >= y                  -- greater than? greater or equal?
x and y                          -- both true?
x or y                           -- at least one true?
not x                            -- flip true/false

Choosing: if / then / else

if age >= 18 then
  print("You can vote!")
elseif age >= 13 then
  print("You are a teenager")
else
  print("You are a kid")
end

Inline Choice: when

let label: String := when age >= 18 "adult" else "minor" end

Loops: from / until

from let i: Integer := 1 until i > 5 do
  print(i)
  i := i + 1
end
-- prints 1 2 3 4 5

Repeat

repeat 3 do
  print("hello!")
end
-- prints hello! three times

Across

Iterate over any collection (Array, String, Map) using its cursor:

across [10, 20, 30] as x do
  print(x)
end
-- prints 10 20 30

Strings iterate by character:

across "abc" as ch do
  print(ch)
end
-- prints #a #b #c

Maps iterate as [key, value] pairs:

across {"name": "Alice", "age": "10"} as pair do
  print(pair.get(0))
end

Functions

function greet(name: String)
do
  print("Hello, " + name + "!")
end

greet("Bob")

A function that gives back a value:

function double(n: Integer): Integer
do
  result := n * 2
end

print(double(5))                 -- 10

Arrays

let colors: Array [String] := ["red", "green", "blue"]
print(colors.get(0))            -- "red"
colors.add("yellow")            -- add to the end
print(colors.length)            -- 4

Maps

let pet: Map [String, String] := {"name": "Max", "kind": "dog"}
print(pet.get("name"))            -- "Max"
pet.put("kind", "cat")            -- update a value

Classes

A class bundles data and actions together:

class Pet
  feature
    name: String
    sound: String

  create
    make(name: String, sound: String) do
      this.name := name
      this.sound := sound
    end

  feature
    speak do
       print(name + " says " + sound)
     end
end

Creating Objects

let cat: Pet := create Pet.make("Mimi", "meow")
cat.speak                        -- "Mimi says meow"

Constructors

A constructor sets up an object when it is created:

class Circle
  create
    make(r: Real) do
      radius := r
    end

  feature
    radius: Real

    area(): Real do
      result := 3.14159 * (radius ^ 2)
    end
end

let c: Circle := create Circle.make(5.0)
print(c.area)                    -- 78.53975

Inheritance

A class can build on another class:

class Animal
  feature
    name: String
    speak do print(name) end
  create
    with_name(n: String) do name := n end
end

class Dog
  inherit Animal
  feature
    speak do
      print(name + " says Woof!")
    end
  create
    with_name(n: String) do Animal.with_name(n) end
end

Design by Contract

Tell Nex what must be true before, after, and always:

class Wallet
  feature
    money: Real

    spend(amount: Real)
      require                    -- must be true BEFORE
        enough: amount <= money
      do
        money := money - amount
      ensure                     -- must be true AFTER
        less: money = old money - amount
      end

  invariant                      -- must ALWAYS be true
    not_negative: money >= 0.0
end

Error Handling

let attempts: Integer := 0
do
  attempts := attempts + 1
  if attempts < 3 then
    raise "not ready yet"
  end
  print("done on attempt " + attempts)
rescue
  print("failed, trying again...")
  retry                        -- jump back to do and try again
end

raise throws an error. rescue catches it (the value is in exception). retry jumps back to the do block and runs it again from the top.

Case / Of

case direction of
  "up"    then print("going up")
  "down"  then print("going down")
  else         print("standing still")
end

Scoped Blocks

let x: Integer := 10
do
  let x: Integer := 99          -- shadows the outer x
  print(x)                      -- 99
end
print(x)                        -- 10

Type Conversion: convert

convert <value> to <name>:<Type>
do
  convert vehicle_1 to my_car:Car
  -- my_car is visible in this block
end
if convert vehicle_1 to my_car:Car then
  my_car.sound_horn
end

Anonymous Functions

let add: Function := fn (a, b: Integer): Integer do result := a + b end
print(add(3, 4))                -- 7

Generics

class Box [T]
  feature
    value: T
  create
    make(v: T) do value := v end
end

let b: Box [Integer] := create Box [Integer].make(42)
b.value -- 42

Assignment

x := 10                         -- set an existing variable
let y: Integer := 20            -- create a new variable
this.name := "Nex"              -- set a field inside a method

That’s it!

Nex reads like English: if...then...end, from...until...do...end, repeat...do...end, across...as...do...end, class...feature...end. Write what you mean, and Nex will check that you mean what you write.