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 arguments - fn greet(who = "world"), no annotation.
  • println(array) prints the real values.
  • Negative string indexing - s[-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,
}
print(msg)                       // 42

Options work the same way:

wyn
var opt: string? = Some("Wyn")
var name = match opt {
    Some(v) => v,
    None => "anonymous",
}
print(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) {
    print("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]
print(nums)                      // [1, 2, 3]

// negative string indexing
var s = "hello"
print(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.22.0