💾 Archived View for ser1.net › post › mozillas-rust-language.gmi captured on 2023-11-04 at 11:21:19. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2022-07-16)

➡️ Next capture (2024-03-21)

-=-=-=-=-=-=-

Mozilla released version 0.1 of it's programming language offering called Rust.  There are a number of things about Rust which are nice; it uses LLVM, which means it gets tail-call-optimization, which Go doesn't have; it has isolated, lightweight tasks, and channels much like Go; I've come across discussions about Erlang-style supervisors, which is encouraging; it has a Ruby-like syntax for closures; it has some limited type inferrence (very similar in scope to what Go can do); and it has pattern matching a-la OCaml, which Go doesn't.  On top of all of this, the executables it produces for small applications are two orders of magnitude smaller than those produced by Go (Go's "Hello World" is 1.2MB; Rust's is 14KB).  I don't have any performance comparisons yet, but I wouldn't be surprised if Rust was (currently) faster than Go. Go's compiler is faster, the value of which increases proportional to the size of the project on which you're working.

Rust

Despite all of this, I haven't switched over to Rust yet; it's a touchy-feel-ey reason, more than anything concrete.  Go feels more mature, despite Rust being older.  The Go library documentation is much better, and the developer tools feel more complete.  And it's just easier to code in; Rust is a bit more wordy in tiny little ways.  For example, to do something multithreaded, in Rust you'll end up doing something like this:

let in = comm::port::int();
let out = comm::chan::int(in);
task::spawn { ||
  some_func(out);
}
let res = comm::recv(in);

ports are for writing to, and chans are for reading from, and never the twain shall meet.  In Go, the equivalent would be:

var inout = make(chan int)
go some_func(inout)
res := <-inout

There in't a huge difference, but the Rust version is more wordy, and not any more clear.  I just get a tiny, nagging feeling that, over time, the verbosity of Rust would start to wear.  Especially with the whole port/chan thing, which smells an awful lot like boiler-plate.

The other thing is that I keep having trouble writing threaded apps in Rust.  At some point in every attempt, something or other blocks me and I can't get around it.  Most recently, it had to do with the fact that you can't send a port to a function if that function is in another task.  This means that you can't share a port between tasks.  You can't do this:

let in = comm::port::int();
task::spawn { || comm::recv(in); }

The Rust compiler raises this as an error (unsendable value).  I will readily admit that this is almost certainly a failure on my part to understand the idiomatic idiosyncrasies of  Rust, and that there may be a way to accomplish this, but my question remains: if you can't share ports between tasks, then how do you implement a single-producer / multiple-consumer multi-threaded application?  I didn't find any code in any of the examples in src/test (in the Rust repository) which demonstrated something like this, and when I asked on #rust IRC, my question was met with silence.

What it all boils down to is that, at least for me, Rust is being a PITA to get started with, whereas Go wasn't.  And in some ways, they're really very similar languages; they both have the "arg TYPE" ordering of type declarations; they both have "type SOMETHING {" structure for records; they have similar threading models and channel communications... but Google, in my mind, at least, has been much more successful at making Go accessible than Mozilla has with Rust.  So for now, I'm going to continue working with Go, and keep an eye on developments in Rust.