[HN Gopher] Koto Programming Language
       ___________________________________________________________________
        
       Koto Programming Language
        
       Author : virtualritz
       Score  : 131 points
       Date   : 2025-03-29 12:14 UTC (10 hours ago)
        
 (HTM) web link (koto.dev)
 (TXT) w3m dump (koto.dev)
        
       | martin-t wrote:
       | The amount of scripting languages _for Rust_ is a symptom of how
       | Rust fails to satisfy the need to write code with less strict
       | requirements.
       | 
       | It makes perfect sense to use Rust as the main language for your
       | application but have areas which are either in the prototype
       | stage, need to be written quicker or which simply don't need the
       | performance. But Rust does not offer a way to enter such a less
       | strict context and such proposals keep getting shot down by the
       | community, even when they are made from core members of the Rust
       | team.
       | 
       | Contrast that with C# which has a dynamic keyword, allows
       | enabling a checked context (not just in code where you can't miss
       | it but also from csproj), has reflection, etc.
       | 
       | I really want Rust to succeed but sometimes the attitude borders
       | on zealotry.
        
         | Sytten wrote:
         | What are you rambling about, this is a sanboxed scripting
         | language to allow your users to define customization at
         | runtime. This has nothing to do with rust, it could be written
         | in C or C++. You would not run random user provided C# in your
         | application at runtime.
         | 
         | It is like saying browser should be coded in C# because C++
         | can't be use instead of JavaScript...
        
           | 01HNNWZ0MV43FF wrote:
           | Since it's written in Rust, that's the easiest place to use
           | the embedding API. https://koto.dev/docs/0.15/api/ I imagine
           | one _could_ use it from C, but it wouldn't be as ergonomic as
           | Lua's C API. And Lua in turn isn't a perfect match for
           | embedding in Rust
        
           | benwilber0 wrote:
           | Or like saying that C++ was somehow deficient just because
           | NodeJS had to be created in order to script v8.
        
           | martin-t wrote:
           | It literally says "for Rust applications" on its front page.
           | 
           | Your tone is insulting and has no place in technical
           | discussions.
        
             | VWWHFSfQ wrote:
             | Describing rust programmers as "zealots" also has no place
             | in a technical discussion.
        
         | Onavo wrote:
         | We need LuaJIT in Rust.
        
           | benwilber0 wrote:
           | This is already available as an optional Lua target in mlua
           | [0]. I recently built a programmable server for Server-Sent
           | Events scriptable with Lua [1]. I chose Lua 5.4, but it's
           | trivial to switch it to LuaJIT, or really any other Lua
           | derivative including Roblox Luau. It's just a matter of
           | enabling the mlua feature you want.
           | 
           | [0] https://github.com/mlua-rs/mlua
           | 
           | [1] https://tinysse.com/
        
         | Philpax wrote:
         | While I would like a Rust-like language that has those things,
         | complaining that Rust, a compiled native language with no
         | runtime whose closest competitor is C++, does not is a little
         | strange to me.
         | 
         | Yes, it is very multi-paradigm and can be used in many domains,
         | but it's not trying to be C# and it can't be C#. I would love
         | to see Rust# as a language, but Rust itself cannot be that
         | language.
        
           | martin-t wrote:
           | Should new languages artificially restrict themselves based
           | on the restrictions of their main competitor even if it's
           | possible to serve a wider range of usecases?
           | 
           | Dynamic can be implemented in a compile-to-native lang.
           | Contexts with different rules as well. Reflection support
           | would likely have overhead which would need a granular opt in
           | mechanism but is very likely possible.
           | 
           | Similarly many features rust is missing like compile time
           | reflection, field in traits, ...
        
             | Philpax wrote:
             | > Should new languages artificially restrict themselves
             | based on the restrictions of their main competitor even if
             | it's possible to serve a wider range of usecases?
             | 
             | Nope - and indeed, we're seeing Rust used in a more diverse
             | set of applications than C++ (e.g. there are several Rust
             | web frontend frameworks, it's a popular WASM language in
             | general, etc)
             | 
             | However, Rust is targeting the same kind of general
             | constraints as C++ for development and deployment, which
             | means it can't add anything that would depend on a runtime
             | or impose an undue burden on users. (Of course, C++ cheats
             | in this regard - RTTI and exceptions - but Rust matches
             | that, and doesn't go beyond.)
             | 
             | > Dynamic can be implemented in a compile-to-native lang.
             | 
             | Requires runtime functionality, and it's not really clear
             | what the resulting semantics would be, anyway: aside from
             | the usual type-safety concerns, how do you deal with
             | lifetimes and other compile-time constraints?
             | 
             | > Contexts with different rules as well.
             | 
             | What kind of different rules? The problem is that any
             | deviation from the rules needs to be reconciled at some
             | point, and that reconciliation has to be watertight: you
             | can't weaken the guarantees somewhere that interacts with
             | safe Rust code, because the weakness you've introduced can
             | spread. This is already a pretty significant issue with
             | unsafe Rust.
             | 
             | Similarly, moving to a higher level of abstraction has
             | similar issues: how do you reconcile the interactions of
             | GC'd objects with the rest of Rust, which expects
             | deterministic destruction and somewhat-predictable object
             | lifetimes?
             | 
             | > Reflection support would likely have overhead which would
             | need a granular opt in mechanism but is very likely
             | possible.
             | 
             | If you're already committing to a granular opt-in
             | mechanism, you might as well use a library, which offers
             | you more options:
             | https://docs.rs/bevy_reflect/latest/bevy_reflect/
             | 
             | > Similarly many features rust is missing like compile time
             | reflection, field in traits, ...
             | 
             | I'll give you compile-time reflection; that _would_ have
             | been quite nice to have, but the Rust Foundation alienated
             | the primary person with a plan (https://thephd.dev/i-am-no-
             | longer-speaking-at-rustconf-2023), so who knows when we'll
             | see the next proposal? I agree that it's a shame, but
             | there's usually ways to work around it (proc macros can be
             | used to patch over a lot of Rust's relative deficiencies)
             | 
             | Field-in-traits has been discussed before, but is
             | complicated due to the borrow checker:
             | https://internals.rust-lang.org/t/fields-in-traits/6933/1
             | 
             | In general, the borrow checker is the primary impediment to
             | copying features from other languages; it's just generally
             | non-trivial to fit them into the Rust paradigm without
             | significant R&D. That's why I think a higher-level Rust
             | would have to be a separate language, not an extension of
             | Rust proper: resolving the collision of semantics between
             | abstraction levels is just too difficult in the general
             | case.
        
         | jakkos wrote:
         | Would you be able to share examples of these "shot down
         | proposals"?
         | 
         | I personally haven't found Rust that difficult to prototype in,
         | when I need to I just liberally use clone/Arc/RefCell.
         | 
         | I see the main benefit of these scripting languages as being
         | able to write/run code at runtime, e.g. live coding music or
         | mods for video games.
        
           | perrygeo wrote:
           | > I personally haven't found Rust that difficult to prototype
           | in
           | 
           | Rust is actually a pretty nice language for prototyping IMO.
           | I agree with your take - Rust has many escape hatches you can
           | use to develop quickly. Then when it comes time to clean up,
           | it's obvious where the deficiencies are (look for all the
           | clones and unwraps, etc)
           | 
           | > I see the main benefit of these scripting languages as
           | being able to write/run code at runtime
           | 
           | Thank you. Some commenters seem to think a scripting language
           | somehow reveals some deficiency in the core language.
           | Reality: not all code is available at compile time. Many
           | applications need some way to inject code without
           | recompiling.
        
           | martin-t wrote:
           | Niko Matsakis made a proposal on his blog for opt-in contexts
           | with relaxed rules (such as implicit conversions) and it was
           | hated, at least on reddit. I doubt he would delete it but i
           | can't find it now.
        
         | HKH2 wrote:
         | Maybe I'm a zealot, but I use Rust-script with cmd_lib. Rust-
         | script lets you define the libraries at the top of the file
         | (instead of in a Cargo file) and cmd_lib gives you macros to
         | call commands directly almost like in Bash. Then you can
         | iterate over the output way faster than in Bash. It recompiles
         | after any changes, and subsequent runs just call the compiled
         | executable. The downside is that the cache does grow, but it's
         | not that noticeable.
        
           | jakkos wrote:
           | I really like the idea of rust-script but last time I looked
           | there didn't seem to be a good way to get rust-analyzer to
           | work when writing a script. Maybe I'm a little too reliant on
           | LSPs but I find writing Rust painful without it, has the
           | situation improved at all since?
        
         | hypeatei wrote:
         | > Contrast that with C# which has a dynamic keyword
         | 
         | `dynamic` has a very narrow use-case and generally shouldn't be
         | used at all (even when prototyping)
         | 
         | I believe it was introduced to make working with poorly
         | designed external libraries easier (e.g. Windows/Office libs)
        
         | BiteCode_dev wrote:
         | I think it's just a convenient and popular language to
         | experiment with.
         | 
         | For production systems, people just use Python + Rust when
         | needing a balance between dynamism and strictness. The tooling
         | to mix them is very mature and the communities are overlapping.
         | 
         | With uv becoming the defacto packaging solution for python, I
         | expect the border to blur even more in the future.
        
       | mostafah wrote:
       | 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 wrote:
         | 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 wrote:
           | I agree. Emacs and its Emacs Lisp are one of the best
           | examples of this design. Thank you for the links.
        
             | nine_k wrote:
             | As an avid Emacs user, can't but agree :)
        
       | fstarship wrote:
       | It seems every scripting language does duck/dynamic typing (as
       | far as I can tell this applies to Koto).
       | 
       | I don't understand why... inferred typing is nearly as easy to
       | use while being more robust.
       | 
       | For me the biggest gap in programming languages is a rust like
       | language with a garbage collector, instead of a borrow checker.
       | 
       | Rust has a lot of features that should be strongly considered for
       | the next generation of programming languages such as
       | 
       | result/sum types
       | 
       | Inferred typing
       | 
       | Not object oriented or overly prescriptive with functional
       | programming.
       | 
       | I think the closest language to filling that gap is occaml (I am
       | not familiar with it).
       | 
       | I have coworker's that are more skilled in domain logic that can
       | write basic self contained programs, but stuff like traits, OOP
       | functional programming is a bridge too far.
       | 
       | I feel like a language that fills that gap could be useful,
       | context is a manufacturing ERP system.
        
         | dustbunny wrote:
         | Check out Wren.
         | 
         | https://wren.io/
         | 
         | Written by Bob Nystrom, author of Crafting Interpretors.
        
           | fstarship wrote:
           | Thanks for your suggestion.
           | 
           | At first glance it appears to be object oriented, which is
           | against preference but not a deal breaker.
           | 
           | However error case looks to be try catch which is a deal
           | breaker.
        
             | pansa2 wrote:
             | > _However error case looks to be try catch which is a deal
             | breaker_
             | 
             | Wren uses coroutines ("fibers") for error handling, which
             | is unusual. But yes, ultimately it does seem to be
             | equivalent to try-catch.
        
           | pansa2 wrote:
           | Wren is dynamically-typed, though
        
           | sramsay wrote:
           | Last release was four years ago.
        
         | oDot wrote:
         | You're describing Gleam
         | 
         | https://gleam.run
        
           | fstarship wrote:
           | Thanks looks great so far.
           | 
           | Also has pattern matching which I should also have mentioned
           | in my top level post.
        
             | macintux wrote:
             | After learning Erlang, it was painful to go back to any
             | language which didn't offer pattern matching. Such a great
             | language feature.
        
             | oDot wrote:
             | I use it in production[0] and it's a delight so far. When
             | Porffor[1] is ready you could compile to WASM through JS
             | for self-contained binaries!
             | 
             | [0]: https://blog.nestful.app/p/why-i-rewrote-nestful-in-
             | gleam
             | 
             | [1]: https://porffor.dev/
        
           | IshKebab wrote:
           | Can you easily embed it though? Looks like it depends on
           | Erlang which means the answer is likely no.
        
             | oDot wrote:
             | It also compiles to Javascript, which runs in a lot of
             | places (to say the least). For WebAssembly, see my other
             | comment about Porffor
        
               | IshKebab wrote:
               | Javascript isn't the nicest thing to embed either tbh. It
               | looks like a nice language but it's clearly not in the
               | same space as Lua or Rhai.
        
         | letmeinhere wrote:
         | For one thing, inferred types may feel easy to use when
         | implemented (well) but they are not easy to implement.
        
         | rapind wrote:
         | I'd keep an eye on Roc https://www.roc-lang.org/
         | 
         | Also, Elixir is working on gradual types, which is something I
         | would keep an eye on. https://hexdocs.pm/elixir/main/gradual-
         | set-theoretic-types.h...
         | 
         | https://www.youtube.com/watch?v=giYbq4HmfGA&t=1s
        
           | no_wizard wrote:
           | I want Clojure on Rust, or a similar LISP.
           | 
           | Such a great programming paradigm that sadly has few breakout
           | successes
        
             | whytevuhuni wrote:
             | I'm having a hard time picturing that. What would it look
             | like?
        
           | cultofmetatron wrote:
           | roc as a language looks really interesting but its by elm
           | devs and I don't have much confidence in their ability to
           | handle the transition to being a widely used language with
           | all the cultural shifts that requires.
        
             | Hasnep wrote:
             | It's created by Richard Feldman who was big in the Elm
             | community, but I think most contributors to the Roc
             | compiler have only used Elm a bit or have never used it.
        
         | ossopite wrote:
         | I think you really are describing ocaml, which is a great
         | language, although its ecosystem isn't the best. It probably
         | inspired most of the features you mentioned in rust. It also
         | supports OOP (hence the O) but it's easy to avoid.
         | 
         | That said, I wouldn't compare it to scripting languages. The
         | lack of implicit conversions / traits / ad-hoc polymorphism
         | means it's not that convenient for scripting.
        
           | nerdponx wrote:
           | Nim was great along these lines when I tried it. But that was
           | before the v2.0 which apparently was accompanied by drama and
           | a fork.
        
             | rattray wrote:
             | What happened?
        
           | threatofrain wrote:
           | Implicit conversion is not _obviously_ that convenient for
           | scripting. The JS community has largely moved to anti-
           | recommend implicit conversion, such as by basically striking
           | `==` from their vocabulary.
        
           | raphinou wrote:
           | Fsharp, which originally was ocaml on dotnet, can also be run
           | as scripts. It is a really practical way to start a project.
           | I blogged about it here: https://asfaload.com/blog/fsharp-
           | fsx-starting-point/
        
             | soulbadguy wrote:
             | Fsharp is such a nice languange. Such a shame that I never
             | seem to get the light it deserves. Between the alternative
             | light syntax, type providers and first class "scripting"
             | mode supported it really was a great middle point between
             | fully scripting language and fast prototyping and full blow
             | projects
        
           | jeltz wrote:
           | Ruby does very little implicit type conversion and is great
           | for scripting. I think implicit type conversion is not
           | required or even a good thing for scripting languages.
        
           | xigoi wrote:
           | What makes OCaml inconvenient for scripting is how difficult
           | it is to run code that uses some external libraries. You
           | basically need to create a whole project structure with
           | several config files, which creates a lot of friction
           | compared to `import numpy as np`.
        
         | rTX5CMRXIfFG wrote:
         | I'm not sure what you're getting at here but none of the
         | features you mentioned are groundbreaking anymore? At least in
         | Swift:
         | 
         | result/sum types = enums whose cases have associated values
         | 
         | inferred typing = Swift "type inference"
         | 
         | Not object oriented or overly prescriptive with functional
         | programming. = Uh, yes
         | 
         | Those features map to Kotlin too
        
           | sanderjd wrote:
           | Yeah I think Kotlin is quite close to the OP's description.
           | But it is perhaps more focused on object orientation than
           | they would like, and also only runs on the JVM.
           | 
           | But if I were to create a self-contained (that is, non-JVM)
           | "Rust-like but with GC", I think it would look a lot like
           | Kotlin.
        
             | karmakaze wrote:
             | I haven't tried it but Kotlin/Native targets platforms like
             | iOS, macOS, Linux, Windows, etc. There's also Kotlin/JS for
             | JavaScript, and a WASM target with limitations.
        
               | lolinder wrote:
               | It's been a few years since I tried Kotlin/Native but
               | even then it was pretty good.
        
               | sanderjd wrote:
               | Neat. I didn't know that.
        
             | valenterry wrote:
             | Rather Scala but leaving out a few parts. Kotlin is very
             | very OOP focussed and comes with a lot of baggage from
             | Java.
             | 
             | Rust-like but with GC is already Scala. The reason is that
             | Scala (unlike Kotlin) focusses on immutability, which makes
             | it more similar to Rust. It's actually even easier to use
             | (no borrow checker) but at the cost of performance.
             | 
             | After Rust, I would see F# as the next closest language,
             | quite far before Kotlin.
        
               | sanderjd wrote:
               | > _Rust-like but with GC is already Scala._
               | 
               | Maybe like _a third_ of Scala. But yeah, Scala has a lot
               | of good parts, it 's also just a huge surface area. I
               | agree that you could pluck a subset out of Scala and make
               | it this "Rust-like but with GC" language.
               | 
               | But it's nigh-impossible to actually make that "only use
               | this subset" idea work in practice, because it just ends
               | up being a bikeshed.
               | 
               | But you're right that the same can be said of the OO
               | focus of Kotlin.
        
           | fstarship wrote:
           | I am aware of 3 "rust inspired scripting" languages that have
           | dynamic types.
           | 
           | Rhai Rune Dyon
           | 
           | Mun is not dynamic, however it does not have string support
           | afaik.
           | 
           | Kotlin and Swift may be better candidates than these
           | scripting languages for my imagined usecase.
           | 
           | Come to think of it, maybe I don't have a point other then
           | there is so many scripting language's inspired by rust that
           | is dropping a major convenience feature, that I am surprised
           | is negotiable (inferred typing ).
        
             | zozbot234 wrote:
             | Rust itself has dynamic types via the Any trait and &dyn
             | Any variables. They are not the default of course, but
             | they're available should you really want them. IIRC C#
             | works similarly, only its feature is called Dynamic
             | instead, or something like that.
        
               | skitter wrote:
               | They're rather different: In Rust types only exist at
               | compile time; dyn Any is a normal trait object, so you
               | can only call the trait's methods. With C#'s dynamic, you
               | can call arbitrary methods and access any fields with
               | type checking of those accesses being delayed until
               | runtime, which works because types exist at runtime too.
               | 
               | Rust's dyn Any corresponds better to C#'s Object; dynamic
               | exists to interface with dynamic languages and is rarely
               | used.
        
           | madeofpalk wrote:
           | I don't think you're disagreeing with parent. I also think
           | these features are not groundbreaking and should be
           | considered table stakes for any new/sane language.
        
         | chris_pie wrote:
         | I'd say F# is closer to filling that gap than OCaml. It's a bit
         | less insistent on being functional and has a more familiar
         | syntax. I find it more practical in general.
        
           | pjerem wrote:
           | I somehow discovered F# by accident and it's really an hidden
           | gem.
           | 
           | Its ahead of its time in basically every aspect, it's 100%
           | compatible transparently with the whole C# ecosystem, it's
           | mature yet still evolving.
           | 
           | The type system is something I never saw before : creating
           | types is so ergonomic and fast that you can create custom
           | type for basically any value of your program without
           | boilerplate if you want.
           | 
           | It's really a refreshing language that anyone should try.
           | 
           | What I really love with it is that it's hard to write (when
           | you are learning it) but incredibly clear to read.
        
             | chris_pie wrote:
             | Also the Units of Measure are a great feature. I think
             | they're a zero-cost abstraction that Rust users love to
             | mention.
        
           | ossopite wrote:
           | I'm curious what you have in mind when it comes to ways in
           | which OCaml is insistent on being functional while F# isn't.
           | After all, OCaml has mutable data structures, mutable record
           | fields, for loops and so on. Is it just that more libraries
           | assume immutability and use functional abstractions?
        
             | chris_pie wrote:
             | To be fair, my knowledge of F# is a bit basic, but I meant
             | stuff like classes (including abstract ones), interfaces,
             | and the ingrained interop with C#.
        
         | haxiomic wrote:
         | Haxe is the best fit for me, think of typescript with
         | functional patterns and inferred typing. Written in ocaml and
         | inspired by the language
        
         | camdenreslink wrote:
         | You could probably write F# in the style that you describe (it
         | is a descendant of OCaml).
        
         | pansa2 wrote:
         | > _It seems every scripting language does duck /dynamic typing
         | (as far as I can tell this applies to Koto)._
         | 
         | It looks like Koto supports type hints - not sure if these are
         | checked at compile-time, run-time, or both.
         | 
         | > _I don't understand why... inferred typing is nearly as easy
         | to use while being more robust._
         | 
         | Is it (nearly as easy to use)? Every static type system seems
         | to have special cases and exceptions which are avoided by
         | dynamic typing. I'd love to find one that's actually simple.
         | 
         | Also, it's definitely not nearly as easy to _implement_ - which
         | is important for a language being designed and built by a small
         | team and targeting a lightweight runtime.
        
           | pansa2 wrote:
           | > _not sure if these are checked at compile-time, run-time,
           | or both_
           | 
           | It looks like Koto only checks types at run-time. That means
           | its type annotations are essentially shorthand for something
           | like Python's `if not isinstance(...): raise TypeError`.
        
             | irh wrote:
             | Yes that's right, they're checked at runtime (with the
             | option to disable the checks if the performance cost is a
             | concern) and failed checks simply throw exceptions.
             | 
             | The hints aren't used for other purposes at compile time
             | yet, but they could enable some warnings.
        
           | tuveson wrote:
           | > Also, it's definitely not nearly as easy to implement
           | 
           | I think this is the real reason why there are so many dynamic
           | language implementations. If you want to implement a dynamic
           | language, you just slap a type tag on your runtime objects
           | and boom, your "type system" is done.
           | 
           | Dynamic languages get a lot of expressiveness "for free",
           | whereas having a really expressive static type system
           | requires a lot of work. It's not that hard to get a type
           | system on the level of C, but if the language is interpreted,
           | it's still going to be pretty slow.
           | 
           | I do think there can be benefits to having typing in a
           | scripting language (and not a bolted-on type system like
           | typescript or mypy). It's much easier to work with an FFI if
           | the type system of the scripting language maps closely to the
           | implementation language. It also does make it much easier to
           | optimize the language down the line, if that becomes a
           | priority. Making a fully dynamic language efficient is very,
           | very difficult.
        
         | IshKebab wrote:
         | I totally agree. I think it's simply because most of these
         | projects are pretty much one-man efforts and implementing
         | static typing is a _lot_ more effort than dynamic typing.
        
         | notnullorvoid wrote:
         | > For me the biggest gap in programming languages is a rust
         | like language with a garbage collector, instead of a borrow
         | checker.
         | 
         | I agree, though I often think Rust is probably good enough. You
         | can use RC or grab a GC crate. It's not as ergonomic as just
         | assuming all values are GCed, but I think it gives the
         | flexibility and fast iteration of working in a GCed language.
        
           | teleforce wrote:
           | Rust is not as good as D in this domain in which D is
           | designed for this, since it's GC by default, please see my
           | other comments.
        
         | valenterry wrote:
         | You are looking for Scala or F#, depending on your choice of
         | ecosystem.
         | 
         | Both come with very powerful features, but you don't need to
         | use them and you can use libraries accordingly. Especially
         | Scala can be made to feel very similar to python
        
         | zozbot234 wrote:
         | Rust will probably gain support for "pluggable" and optional
         | garbage collectors as part of its upcoming local allocators
         | API. This will ultimately give devs the best of both choices -
         | use tracing GC where it's actually needed (because you're
         | working with totally general graph-like data and that's the
         | only feasible memory management strategy) and manual memory
         | management (supplemented by RAII and reference counting)
         | elsewhere - for other parts of the program that don't have to
         | manage general "spaghetti" graphs. Unfortunately the way GC's
         | trace objects and collect garbage varies wildly among
         | implementations, so there's no easy way to standardize a
         | "generic" interface to pluggable garbage collection, that all
         | custom crates might be expected to tap into by default. But
         | other uses should be quite feasible.
        
           | SkiFire13 wrote:
           | > Rust will probably gain support for "pluggable" and
           | optional garbage collectors as part of its upcoming local
           | allocators API.
           | 
           | Source? AFAIK there's no confirmed upcoming allocators APIs,
           | and even if there was they would just allow reusing the
           | builtin `Box`/`Vec`/etc etc with custom allocators. This is
           | not much different than what you could do with a custom type,
           | so I find it hard to believe it would allow garbage
           | collectors that are not possible right now.
        
         | simon_void wrote:
         | check out Borgo https://github.com/borgo-lang/borgo It is Go
         | with algebraic datatypes!
        
         | beagle3 wrote:
         | You are describing Nim.
        
         | mirekrusin wrote:
         | MoonBit lang is probably closer. Beautiful language.
        
         | teleforce wrote:
         | >For me the biggest gap in programming languages is a rust like
         | language with a garbage collector, instead of a borrow checker.
         | 
         | I cannot agree more that's the much needed sweet
         | spot/Goldilock/etc. Personally I have been advocating this
         | approach for some times. Apparently the language is already
         | widely available and currently has stable and wide compiler
         | support including the venerable GNU compiler suite (GDC). It
         | also one of the fastest, if not the fastest programming in
         | existence for both compilation and execution [1].
         | 
         | It has been beating Fortran in its number crunching territory,
         | no small feat given the Fortran pedigree with many languages
         | still depending on Fortran based infrastructure for their
         | number crunching capabilities including Matlab, Julia, Rust,
         | Go, C, C++, etc [2].
         | 
         | It also has a nice bulti-in REPL system due to its very fast
         | compilation and execution [3].
         | 
         | For an excellent overview of D programming language please
         | check this presentation at ACCU conference [4].
         | 
         | [1] D website:
         | 
         | https://dlang.org/
         | 
         | [2] Numeric age for D: Mir GLAS is faster than OpenBLAS and
         | Eigen:
         | 
         | http://blog.mir.dlang.io/glas/benchmark/openblas/2016/09/23/...
         | 
         | [3] Why I use the D programming language for scripting (2021):
         | 
         | https://news.ycombinator.com/item?id=36928485
         | 
         | [4] How DLang Improves my Modern C++ and Vice Versa - Mike Shah
         | - ACCU 2024:
         | 
         | https://youtu.be/CnKsOak0DHU
        
         | nine_k wrote:
         | The point of many scripting languages is quick tinkering,
         | mucking with stuff in a REPL, on top of a complex contraption
         | of already-live objects. This works well with duck typing. It
         | does not work with nice static type inference, because once you
         | change something high upstream, it potentially invalidates
         | everything downstream, your entire current session you've spent
         | an hour building.
         | 
         | "Everything should be built top-down, except for the first
         | time" (See #15 in https://www.cs.yale.edu/homes/perlis-
         | alan/quotes.html)
        
         | sparkie wrote:
         | > I don't understand why...
         | 
         | Because dynamic typing has its own advantages, which are worthy
         | of experimentation even if you perceive absence of static
         | typing as a weakness.
         | 
         | Gradual typing can offer us the benefits of both worlds.
         | 
         | > inferred typing is nearly as easy to use while being more
         | robust.
         | 
         | Implementing type inference can be fairly trivial if your types
         | are all disjoint. Hindley-Milner type inference is well studied
         | and there's plenty of literature.
         | 
         | But as soon as you introduce subtyping, the traditional methods
         | are not sufficient. It's only in the past decade that good
         | solutions have been discovered, notably Dolan & Mycroft's
         | MLsub[1], based on Dolan's Algebriac Subtyping thesis[2], and
         | Parreaux & Chau's MLstruct[3], which uses a boolean algebra
         | approach[4]. Type inference with subtyping is not a solved
         | problem - these developments are big steps forward, but there
         | are still open problems under research.
         | 
         | Subtyping doesn't imply object-oriented. Structural typing (ie
         | "static duck typing") is a form of subtyping.
         | 
         | [1]:https://github.com/stedolan/mlsub
         | 
         | [2]:https://www.cs.tufts.edu/~nr/cs257/archive/stephen-
         | dolan/the...
         | 
         | [3]:https://github.com/hkust-taco/mlstruct
         | 
         | [4]:https://dl.acm.org/doi/pdf/10.1145/3563304
        
           | zozbot234 wrote:
           | > Gradual typing can offer us the benefits of both worlds.
           | 
           | Gradual typing has much the same overhead as other kinds of
           | dynamic typing. It's broadly appropriate as part of the
           | interface between separately-developed software components,
           | and not very much otherwise.
        
             | sparkie wrote:
             | Gradual typing is static typing augmented with a known
             | static type `dynamic`, and some rules by which conversions
             | to/from `dynamic` are statically checked, called
             | consistency.
             | 
             | A program in a gradually typed language which does not use
             | `dynamic` is fully statically checked and has no overheads.
             | The overheads only appear when `dynamic` is used.
             | 
             | This is why it offers the best of both worlds. We get
             | static typing everywhere where we're not using dynamic, and
             | when we do use dynamic, we can basically use it however we
             | want and have the benefits of dynamic typing, because from
             | the static perspective, dynamic ~ dynamic, regardless of
             | what the runtime type is.
             | 
             | The important innovation is that consistency (~) is not
             | transitive - so it doesn't allow us to implicitly convert
             | one type to another - only conversions to/from dynamic are
             | implicit, and other conversions must be done explicitly.
             | 
             | Obviously, this provides an "escape hatch" from static
             | typing where we do use it - we can get around some static
             | type check by casting to/from dynamic explicitly, but this
             | works out well in practice.
             | 
             | C# is an example of a gradually typed language since v4
             | which introduced `dynamic`.
             | 
             | Haskell is close , in that it has the type `Data.Dynamic`,
             | but it doesn't support implicit conversions to/from it,
             | which would be possible if it had a consistency rule. We
             | have to do the conversions explicitly.
             | 
             | https://jsiek.github.io/home/WhatIsGradualTyping.html
        
         | amedvednikov wrote:
         | > For me the biggest gap in programming languages is a rust
         | like language with a garbage collector, instead of a borrow
         | checker.
         | 
         | https://vlang.io
         | 
         | GC, sum types, result/option types, interfaces, no OOP, fast
         | compilation.
        
         | egl2020 wrote:
         | > I don't understand why.
         | 
         | Favors minimal text entry. You keep the type information in
         | your head and enter fewer tokens. Historically you also reduced
         | the work and improved responsiveness for the interpreter, which
         | might have been running on an 8- or 16-bit computer at 5 MHz.
        
       | brookritz wrote:
       | Jabdah
        
         | sagacity wrote:
         | Strange voice coming from the space!
        
       | tzury wrote:
       | 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 wrote:
         | 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.
        
       | chaosprint wrote:
       | 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 wrote:
         | 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.)
        
       | esafak wrote:
       | Would this compile fast enough to be used in shell scripts?
       | #/usr/bin/env koto
        
         | irh wrote:
         | Yes! I'm using it for adding commands to Helix.
         | 
         | e.g.
         | https://github.com/irh/dotfiles/blob/main/scripts/.scripts/t...
        
       | mentalgear wrote:
       | > Syntax: [...] minimizing visual distractions, while also
       | managing to avoid inexpressive terseness.
       | 
       | Nice! Now, if it only had type support.
        
         | pansa2 wrote:
         | 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."
        
           | nine_k wrote:
           | 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.
        
           | Mawr wrote:
           | 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_.
        
           | irh wrote:
           | 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...
        
         | iTokio wrote:
         | It has optional types
        
       | seivan wrote:
       | The documentation and integration with Rust for this amazing,
       | well done! Like other commenters, I also wish it had better
       | static typing and looked more like Elixir with anonymous sum
       | types and template literal types.
        
       | amadoury wrote:
       | Koto means big brother in Fulani (a West African language).
        
       | replwoacause wrote:
       | Elegant syntax!
        
       | fithisux wrote:
       | Koto? Like the Italo-Disco band?
        
         | nine_k wrote:
         | Or like the Japanese musical instrument?
         | https://en.wikipedia.org/wiki/Koto_(instrument)
        
           | irh wrote:
           | Yes it's named after the instrument, although I'm happy to
           | hear about the Italo disco connection =)
        
       | account-5 wrote:
       | 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.
        
       | irh wrote:
       | 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 wrote:
         | 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 wrote:
           | 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/
        
       ___________________________________________________________________
       (page generated 2025-03-29 23:01 UTC)