--
← Back to blog
Expressions, Operators, and Pattern Matching

Expressions, Operators, and Pattern Matching

Operators

NSL operators from lowest to highest precedence:

| Precedence | Operators |

|------------|----------|

| Assignment | = += -= = /= %= *= ??= |

| Ternary | X if cond else Y |

| Or | or |

| And | and |

| Equality | == != |

| Comparison | < <= > >= is |

| Range | .. ..< ..= |

| Add/Sub | + - |

| Mul/Div | * / % |

| Power | ** |

| Unary | - not ! |

| Postfix | . ?. () [] |

Pipe Operator

Chain operations left-to-right:

let result = data
    |> filter(fn(x) => x > 0)
    |> map(fn(x) => x * 2)
    |> sort
    |> reverse
print(result)

The pipe passes the left side as the first argument to the right side.

Comprehensions

Build lists with inline iteration:

let squares = [x * x for each x in range(10)]
let evens = [x for each x in range(20) where x % 2 == 0]

Null Safety

# Null coalescing -- use default if null
let port = config.port ?? 8080

# Optional chaining -- returns null if any part is null
let city = user?.address?.city

# Elvis -- use fallback if falsy
let name = inp ?: "anonymous"

# Null-coalescing assignment
x ??= default_value

Spread Operator

# Spread in lists
let combined = [...list1, ...list2, extra_item]

# Spread in dicts (merge)
let merged = {...defaults, ...overrides, debug: true}

Ranges

let r1 = 0..10      # exclusive: 0,1,2,...,9
let r2 = 0..=10     # inclusive: 0,1,2,...,10
let r3 = 0..<10     # explicit exclusive (same as ..)

String Interpolation

let x = 42
print(f"The answer is {x}")
print(f"Double: {x * 2}, Half: {x / 2}")

Pattern Matching

NSL has powerful pattern matching with match/given:

match status_code
    given 200
        print("OK")
    given 301 | 302
        print("Redirect")
    given 400..500
        print("Client error")
    given 500..=599
        print("Server error")
    otherwise
        print("Unknown")

Pattern Types

Literal: exact value match

given 42
given "hello"
given true

Or-pattern: match any of several values

given 1 | 2 | 3
given "yes" | "y"

Range: inclusive or exclusive ranges

given 1..10       # 1 to 9
given 1..=10      # 1 to 10

Wildcard: match anything

given _

Binding: destructure dict with _type field

let result = {_type: "Ok", value: 42, msg: "success"}
match result
    given Ok(value, msg)
        print(f"Got {value}: {msg}")
    given Err(message)
        print(f"Error: {message}")

Guard: add a condition after the pattern

given x when x > 0
    print(f"Positive: {x}")
given x when x < 0
    print(f"Negative: {x}")

switch/case/default also works as an alias for match/given/otherwise.

Dict and List Access

let d = {name: "Alice", age: 25}
print(d.name)        # dot access
print(d["name"])     # bracket access

let list = [10, 20, 30]
print(list[0])       # 10
print(list[-1])      # 30 (negative indexing)

Type Checking

print(type(42))        # "int"
print(type("hi"))      # "string"
print(is_list([1,2]))  # true
print(42 is int)       # true (is keyword)

Truthiness

Falsy values: null, false, 0, "", [], {}. Everything else is truthy.

All Posts