Koto 0.16

July 23, 2025

Koto 0.16 has been released, including automatic code formatting, various language improvements, easier conversions to Rust types, and more.

Many thanks to the contributors who helped to make this release happen!

Koto?

Koto is a free and open-source programming language which is designed to be an ideal companion scripting language for Rust applications.

If this is the first time you're reading about Koto, you can learn more on the About Koto page, and you can take a look at the language guide.

Automatic Formatting

Automatic formatting of Koto scripts is now supported by Koto's LSP server, and by the CLI's new --format option, which significantly improves Koto's editing experience. The formatting logic is well tested, but it is new, so please report any bugs, unexpected limitations, or strange results by opening an issue.

Language Improvements

Koto v0.16 introduces several quality-of-life improvements to the language (see the changelog for a complete list):

Optional Arguments

Function arguments can now specify default values that will be used when arguments are omitted in function calls.

# Previously, default argument values were typically defined like this:
f = |a, b|
  a + (b or 42)

# In 0.16, you can specify the default value along with the argument:
f = |a, b = 42|
  a + b

f 10
#: 52

See the section on optional arguments in the language guide for more details.

Wildcard Imports

All items from a module can now be imported using * wildcard syntax.

from number import *
assert_eq pi * 2, tau

Power Operator

A power / exponentiation operator has been added (^, along with ^= and corresponding metakeys), replacing the core library's number.pow function.

2 ^ 3
#: 8

Meta Object Improvements

If an object defines equality comparison using @==, then inequality (!=) will now automatically defer to the custom @== implementation (unless @!= is explicitly defined).

Similarly, an object now only needs to define @< and @== for the runtime to automatically derive the behavior of all other comparison operators.

foo = |n|
  data: n

  @==: |other| self.data == other.data
  @<: |other| self.data < other.data

# The result of != is derived by inverting the result of @==
foo(99) != foo(99)
#: false

# The result of > is derived from @< and @==
foo(123) > foo(-1)
#: true

Objects can also now define arithmetic operations when they appear on the right-hand-side of expressions using r-prefixed meta operators (@r+, @r*, etc.). Custom operators on the left-hand-side of an expression take precedence, with the RHS being used as a fallback.

Improved Koto ↔ Rust Value Conversions

Converting between Koto values and Rust types is now easier thanks to Serde support.

Rust types that implement Serialize can be converted into Koto values with to_koto_value, and types implementing Deserialize can be created from Koto values using from_koto_value.

For example, the following Koto script accesses a request value from the prelude, and then exports a map containing caption and numbers entries.

match request
  'one_to_four' then
    caption = 'one to four'
    numbers = 1, 2, 3, 4
  'five_to_eight' then
    caption = 'five to eight'
    numbers = 5, 6, 7, 8

export {caption, numbers}

In Rust, the request value can be created from an enum that implements Serialize:

#[derive(Serialize)]
#[serde(rename_all = "snake_case")]
enum Request {
    OneToFour,
    FiveToEight,
}

koto.prelude()
    .insert("request", to_koto_value(Request::FiveToEight)?);

The exported map can then be converted into a struct that implements Deserialize:

#[derive(Deserialize)]
struct Exported {
    caption: String,
    numbers: Vec<i64>,
}

let exported: Exported = from_koto_value(koto.exports().clone())?;

See the complete example here.

...and more!

These are a few highlights, see here for the full list of changes in v0.16.