[kwlug-disc] On Rust
Mikalai Birukou
mb at 3nsoft.com
Sun Mar 1 12:16:58 EST 2026
>> The song: https://www.youtube.com/watch?v=04I_dPHFd7I
> Sarcastic style: https://www.youtube.com/watch?v=B2gmKy3pHkw
Another sarcastic but with dense presence of nuggets per second:
https://www.youtube.com/watch?v=TGfQu0bQTKc
- Indeed, C and in some expectation C++, are low level languages. They
make instructions for processor.
You wonna make program be faster? All you can do is reduce number of
instructions.
So, every time I do .clone() on a string, this is a place of creating
resource, allocating memory. In comparison to C/C++, it is same, but
cleaner. If I want to reduce number of instructions, I need to rethink.
Yes, Rust nudges you into making decisions. This might be a cognitive
tension people complain about.
- Around 8:33 -- .into(), .into() -- these are steps for morphing data,
usually from one human abstraction to another, that may even not move
those bytes at all, and amount to zero instructions. With C/C++ it is a
pointer. See, how "pointer" says nothing about what is it for.
Name of variable is used for other "biz-logic" meaning and adding type
info to name is not nice to read.
- In the same spot -- .unwrap(), unwrap() -- these are branches of
conditions your code goes. Like exceptions, that fly away. Or non-zero
int status, that again, you need documentation for. Rust type of that
other thing is a documentation.
[side note] TypeScript (JavaScript) I kinda use on promising calls both,
overall try + catch wrap, and more localized .catch(). [/side note]
- Around 0:49 -- letting threads panic. This is like discussions about
killing Node process, if error is unhandled. Well, Rust compiler
meticulously checks all paths of execution. Like Java, if all exceptions
where checked (?).
Now, when you develop, with little test that evolves, correctly
failing/unwrapping flow is what you wanna see. We write code bit by bit,
section by section. This I write now, and it has those other branches,
that I quickly unwrap/panic in test now, and articulate later handling
of this other execution direction.
Its like, when you clime mounting, you need three points of contacts at
any given time. Interim testing gives you that.
- Around 1:11, and whole memory approach.
There is this saying. Garbage collector is not a problem. Garbage is a
problem. You may write Java/JavaScript programs where GC doesn't have to
be present. But it is one of those "why do you write it in a convoluted
way".
Neither Rust nor Java (GC style approach languages) believe that human
remembers all allocations of memory. They just have different reactions.
Java-like worlds put machinery under your code that is bigger and more
complex, than your code. That is why this is neither low level, nor
fast/efficient.
Rust meticulously goes with you through all minute details of
allocations that need to happen to support your abstractions. They have
to distill into simpler instructions. And on 3:49 there is this funky
list enumerating all possible things that happen on lower level. In
contrast, with C you have a pointer, that has to go through all those
situations, but without it being systematically compared by compiler
with your intentions.
There are three approaches: (Java) lang's runtime does it for you, (C)
lang let's you do anything "your gun and your foot" style, (Rust) lang
allows you to do low level, but checks it, and has an explicit
meticulous enumeration within types.
Oh, if that section is touched by another thread, processor needs to
sync locations in cache? Is it what Rust's Sync hints at? Someone needs
to put those instruction in. What if that is never changed. May be no
need to add syncing instructions. How is it expressed in code. Rust has
it. In C one has to remember it, apparently.
- After 1:14, "In Rust you don't need to worry about memory. You need to
worry about borrowing."
This is a place about, "will lang allow you change map, when you iterate
over it". This isn't even a question about threads and async. Yet,
owning and borrowing are human concepts. This is genius in terms of
ergonomics. And yes, enforcement of borrowing and ownership ensures that
low level instruction do what you intended to do.
Okay. Does JavaScript has a way to express at code-typing time that
bytes array you gave to worker, efficiently, without copying, you can't
touch? It is a runtime exception. And, you had that array, and you gave
it completely. So, variable can't have it. Rust's ownership and
borrowing captures this nicely. And current iteration about lexical form
isn't the first they had, and feels ergonomic.
It so happens, that if thing is readonly, you can skip lots of
instructions, and still do multithreading correctly. And this
realization pushed towards perfecting ownership/borrowing and dropping
other things, turning Rust into low level instrument (2:26). Seriously,
async and threads are library addition. Processor sync instructions and
like are placed into core type like Sync (I am floating here, but this
is a vibe I am getting), only allowing libraries to add threads and async.
- 2:31, parallelization "... [pause], in other languages you don't have
parallelization".
True for JavaScript and Pythons (GIL). Go? You have channels to throw
things between threads, but code runs in a thread. Think of it as V8 is
JavaScript engine, and runtime allows to have two engines, expressed as
WebWorkers, and you send messages.
Rust has move and sync, done for you by Rust, but if you gave things
that can't move and sync, Rust will ask you. C won't ask you.
Java has all move and sync instructions for you. And there may be a
price. Go's not really multi-threading is a result of pondering about Java.
Same, but with more social reactions and aforementioned points implied
and appreciated: https://www.youtube.com/watch?v=co3ewqQlX-8
More information about the kwlug-disc
mailing list