Skip to content(if available)orjump to list(if available)

Koto Programming Language

Koto Programming Language

151 comments

·March 29, 2025

chaosprint

Should compare with Rhai (https://rhai.rs/)

I found rhai's syntax very straightforward, and I could almost accomplish my needs just by looking at some basic examples.

I use Rhai in wasm, and it can handle real-time audio blocks, which is really impressive:

https://glicol.org/tour#meta2

nine_k

Rhai looks somehow more OO, and is somehow conceptually bigger, with function overloading, operator overloading, currying, etc. Koto looks more like FP an stream processing, with pervasive anonymous functions, very simple data structures, and an emphasis on iterators.

Rhai also offers some safety guarantees: no panics, no stack overflows, etc. Rhai seemingly requires slightly less ceremony when interfacing with Rust: direct use of many things, as opposed to implementing a trait to interact with Koto.

(Disclaimer: I spent 5 minutes skimming the docs of each.)

spacechild1

Isn't Rhai extremely slow? The website itself says that it's roughly 2x slower than Python3: https://rhai.rs/book/about/benchmarks.html. Apparently, Rhai doesn't even compile to bytecode and instead walks the AST! This doesn't sound like a language I would pick as for DSP...

On the other hand, you can always write your own Rhai interpreter if necessary. And if you restrict the language to a limited set of features, which you need to do anyway to keep it realtime-safe, you could even compile it to native code.

> and it can handle real-time audio blocks, which is really impressive:

Any scripting language can do this as long as you stick to operations that don't cause memory allocations, system calls or other non-realtime-safe operations.

For example, you can use Lua to write process functions for Pd objects: https://agraef.github.io/pd-lua/tutorial/pd-lua-intro.html#s...

The question is rather how much you can do in a given audio callback.

---

All that being said, Glicol is very cool!

chaosprint

You are absolutely right. Thanks for the correction and info!

I gave Lua a shot, but getting the toolchain set up in wasm was a hassle:

https://bytedream.github.io/litbwraw/introduction.html

So at least I can say Rhai has some advantages on syntax and compatibility with wasm

spacechild1

That's a valid point. Being native to the host language (Rust) is generally a big advantage.

I just don't really understand why Rhai uses an AST walking interpreter, that's basically the least efficient way of implement a scripting language. Once you have an AST, a byte code compiler/interpreter is not really hard to implement, so I'm wondering why they knowingly leave so much performance on the table...

thayne

Is koto any faster?

irh

In my tests it's been ~1.5-2x faster than Rhai, but Koto's still some way behind Lua in benchmarks so I'm not trying to make a big claim here (although that said one of the reasons I started work on Koto was to avoid the runtime overhead of Lua <-> Rust conversions, e.g. Koto shares the same string representation as Rust, Koto lists are just wrapped `Vec`s, etc).

0x3444ac53

I looked into Rhai but was disappointed that it doesn't have first class functions.

irh

Koto creator here, nice surprise to see this on HN so I'm a bit late to the discussion. Happy to answer any questions!

riidom

Would you say Koto (or some direct competitors, for that matter), is viable to learn when I otherwise don't intend to learn Rust at all? But let's say, want to keep the option open to participate in Rust-based projects which support Koto et al.?

irh

Yes I would certainly hope so, you shouldn't need to know any Rust if you want to learn Koto. The guide assumes that the reader has some general experience with programming, but not from using any specific language.

https://koto.dev/docs/next/language/

epage

What are your plans for language and in-language library compatibility?

irh

Limited for now, Koto's main role as an embedded language has meant that I haven't had a need, but I would like to provide bindings for other languages at some point, and to enable dynamically loaded Rust libraries.

I'd start by trying UniFFI [1] which looks much simpler than the approach of manually writing a C API and using that as a foundation for higher-level language bindings.

This would also likely be the starting point for a package management system (if there ends up being demand for one). Rust doesn't have a stable ABI so to make sure that dynamically loaded Rust packages are compatible, either Koto would need to be in the business of Rust toolchain management so that packages can be recompiled when needed, or an API layer would be needed. There are some projects that provide ABI-compatibility shims but I don't like the idea of having two separate approaches to FFI, so I'd want to try to build on the foreign-FFI layer once it's in place.

I'm half hoping that by the time I'm interested in working on this Rust will have decided to pursue ABI stability. And there's also something in the back of my mind that's yelling 'Wasm!' at me but I would need someone wiser to convince me that it would be the right direction.

[1] https://github.com/mozilla/uniffi-rs

epage

Sorry, I meant the Koto language and built-in library compatibility story. Whats on the roadmap for a 1.0 and will you allow a 2.0? One of my annoyances with Tcl and Lua is their breaking changes would be pushed into my application and I'd have to decide what version of the language to target and have a plan for changing it.

I'm fine with the Rust API breaking compatibility.

null

[deleted]

mostafah

Very cool. I really like the idea of implementing higher level features as extensions on top of a smaller core. I wish real scripting languages like this were more common and in use. Lua comes to mind when thinking about a generic scripting language, but even that is not that widespread.

nine_k

I think "implementing higher level features as extensions on top of a smaller core" is a hallmark of the Lisp family. Check out Fennel [0] or Janet [1] for two different approaches. On top of everything, Fennel is 100% Lua-compatible.

[0]: https://fennel-lang.org/

[1]: https://janet-lang.org/

mostafah

I agree. Emacs and its Emacs Lisp are one of the best examples of this design. Thank you for the links.

nine_k

As an avid Emacs user, can't but agree :)

aerzen

Recently I've started evaluating new languages in terms of "how difficult would it be to read working code in this language, written by an insane person".

After looking at this for 5 minutes it seems it is better than rhai according to my metric. But not necessarily better than lua.

irh

Haha well I'm sure if you put your mind to it you could create some madness in Koto!

If it helps here's a git blame helper script I made for Helix (as an example of practical code without any effort put in to making it readable for others): https://github.com/irh/dotfiles/blob/main/scripts/.scripts/g...

tzury

Interesting.

At the time we did it with Lua.

We extended Nginx and Envoy-proxy with a Rust library (and a server), and added a Lua interface, so users can further tweak the config and the flow.

https://github.com/zuriby/curiefense/tree/main/curiefense/cu...

benwilber0

I've used OpenResty extensively which is basically just nginx + luajit with a lot of additional APIs and features. The nginx-lua-module is available separately from the OpenResty distribution of nginx, so you can just install and run it as a dynamic nginx module.

tzury

Indeed, OpenResty comes with Lua and LuaJIT built-in. Earlier version where we've implemented all in Lua, had no need for that. However, as we went fro Lua to Rust (and speed up by using only 15% CPU comparing to the Lua), we added that Lua interface support to the rust, and it worked like a charm.

account-5

If I was going to chose a scripting language for rust I'd pick nushell's syntax. Nushell is an amazing shell and it's syntax is one of the reasons why.

esafak

Would this compile fast enough to be used in shell scripts? #/usr/bin/env koto

irh

Yes! I'm using it for adding commands to Helix.

e.g. https://github.com/irh/dotfiles/blob/main/scripts/.scripts/t...

amadoury

Koto means big brother in Fulani (a West African language).

replwoacause

Elegant syntax!

mentalgear

> Syntax: [...] minimizing visual distractions, while also managing to avoid inexpressive terseness.

Nice! Now, if it only had type support.

pansa2

It says Coffeescript and Moonscript influenced Koto's syntax, which is a little worrying. IMO those languages are a little too flexible and sail too close to ambiguity - very small changes to code can sometimes radically change its meaning.

Edit: Sure enough, "whitespace is important in Koto, and because of optional parentheses, `f(1, 2)` is not the same as `f (1, 2)`. The former is parsed as a call to f with two arguments, whereas the latter is a call to f with a tuple as the single argument."

Mawr

Oh it has optional parentheses? Into the trash it goes.

I'm guessing because "it's cleaner/simpler", but that's a shallow understanding of those words. Just because there are two characters fewer on the screen doesn't make the code simpler. Simple semantics are what you should aim for and inconsistencies like these throw a wrench into that.

For example, strings in JSON vs YAML. Isn't it "simpler" to not have to quote every string? So long as your string isn't "no" that may be true. So now instead of a simple mental model of "every string must be quoted" it's "strings don't need quotes except for these specific exceptions that cause issues: <list>". So much simpler... sigh.

dboreham

> Oh it has optional parentheses? Into the trash it goes.

<virtual high five>

irh

What I've had in mind with Koto is that when I need strictness and precision I'll generally be using Rust, and Koto is more intended for another aspect of programming where I want things to be much more fluid and easy-going.

My thinking is that the potential footgun here is outweighed by the win of paren-free calls for quick scripting / rapid iteration, but it certainly counts towards the language strangeness budget [1] so I figured it was worth pointing out in the guide.

[1] https://steveklabnik.com/writing/the-language-strangeness-bu...

nine_k

Oh, the usual Coffeescript footguns :(

One of the problems of terse syntaxes is that one typo away from a syntactically valid program lies another syntactically valid program with entirely different semantics.

I prefer a syntax that has enough "gaps" between syntactic constructs, so that a single typo usually leads to an obvious syntax error. In this regard, Python or Java or TS are comfortable, Haskell or Lisp or C are okay, and Coffescript or Scala or C++ are terrible.

pepa65

Can "always (or never) use parentheses for function calls" be enforced..?

irh

Koto's dynamically typed, but optional type checks were introduced in 0.15: https://koto.dev/docs/0.15/language/#type-checks

iTokio

It has optional types

shahriarhus

It's reminds me of Lua for C++, am I correct?

irh

Yes, I was missing a 'companion language' for Rust similar to Lua for C and C++, I tried Lua bindings and other Rusty scripting languages but felt like starting a new project would be worthwhile.

f18m

Is this the equivalent of Lua for Rust?

irh

Yes that's essentially where it started, although it feels quite different to use now.