Skip to content

What's New in v1.14

"The Polish Release" — the optional and result types you already use, now with the clean syntax they always deserved, plus a handful of ergonomic fixes that remove the last bits of ceremony from everyday code.

It's all backward compatible — no source changes are required to upgrade.

Highlights

  • Clean optional/result return types — write -> int?, -> string?, and -> Result<int, string> directly. The old mangled names are gone.
  • match as an expression on any Option/Result, with any payload type.
  • Type-inferred default argumentsfn greet(who = "world"), no annotation.
  • println(array) prints the real values.
  • Negative string indexings[-1] is the last character.
  • if/else where all branches return no longer needs a trailing return.

Clean Optional and Result Return Types

You can now annotate a function's return type with the sugar directly — int?, string?, or Result<int, string> — instead of a mangled type name:

wyn
fn find(t: int) -> int? {
    if t > 0 { return Some(t) }
    return None()
}

fn parse(s: string) -> Result<int, string> {
    if s == "" { return Err("empty") }
    return Ok(42)
}

Some/None/Ok/Err in the body lower to the right type automatically, and the signature reads exactly the way you'd write it in prose.

match as an Expression

match on an Option or Result now produces a value in expression position, for any payload type — so you can fold both arms into a single binding:

wyn
fn parse(s: string) -> Result<int, string> {
    if s == "" { return Err("empty") }
    return Ok(42)
}

var r = parse("42")
var msg = match r {
    Ok(v) => v.to_string(),
    Err(e) => e,
}
println(msg)                       // 42

Options work the same way:

wyn
var opt: string? = Some("Wyn")
var name = match opt {
    Some(v) => v,
    None => "anonymous",
}
println(name)                      // Wyn

Type-Inferred Default Arguments

The type of a default parameter is inferred from its value, so the annotation is optional:

wyn
fn greet(who = "world") -> string {
    return "Hello, ${who}!"
}

fn dial(host = "localhost", port = 8080) {
    println("Connecting to ${host}:${port}")
}

greet()              // Hello, world!
greet("Wyn")         // Hello, Wyn!
dial()               // Connecting to localhost:8080
dial("0.0.0.0")      // Connecting to 0.0.0.0:8080

Typed defaults (who: string = "world") still work if you prefer to be explicit.

Everyday Ergonomics

A few smaller fixes remove common friction:

wyn
// println prints an array's real values
var nums = [1, 2, 3]
println(nums)                      // [1, 2, 3]

// negative string indexing
var s = "hello"
println(s[-1])                     // o — last character

// if/else where every branch returns needs no trailing return
fn classify(n: int) -> string {
    if n > 0 {
        return "positive"
    } else {
        return "non-positive"
    }
}

Upgrading

bash
wyn --version        # 1.14.0

No source changes are required — v1.14.0 is a drop-in upgrade over v1.13.0. If you were writing mangled return types like -> OptionInt or -> ResultInt, you can now replace them with -> int? and -> Result<int, string>, though the old forms still compile.

See also

MIT License — v1.14