Rust lang vs V lang

C++ references work like that, roughly. This is often convenient, but also frequently makes certain things incredibly difficult. For example, try populating a std::vector<int&> in C++.

Rust's existing auto(de)ref in method calls seems to be quite a good balance here.

9 Likes

Yes, I'm not keen on that aspect of C++. I think in C++ I'd use a std::vector<int*> instead, as it would be much easier to handle, and mean almost the same thing.

Maybe it is necessary for Rust to make explicit the difference between ref and value in this way. However, I think this sort of thing puts off newcomers to the language. Most modern languages, from Scala to Go, just give you one way to represent any object, but in Rust or C++ you have to choose between value, reference, ref-counted, atomic-ref-counted (OK the last two are harder to differentiate in C++) and maybe other choices too. I like the way V allows you to just use objects, and the compiler decides whether to use values or references. But maybe that is just that V is a different language, and as I have discussed, a much less capable one.

One area where I still get confused in Rust is what I need to iterate through a collection. Sometimes I just specify the collection, and auto-deref gives me the iterator. Sometimes I have to add an ampersand. And sometimes I have to write .iter().

I'm not sure how Rust could be even more explicit about this without it becoming bothersome.

Almost all the "modern languages" that you have in mind have a design choice in common, and that design choice is garbage collection.

Being able to manipulate everything by infinite-lifetime reference, which are implemented as garbage-collected pointers by default and may or may not be optimized into something more efficient by the compiler (e.g. a stack allocation), has unquestionable ergonomic benefits when you want to either 1/write programs more quickly without caring about N different parameter-passing conventions or 2/learn the language quicker.

The price to pay, however, is that you will also get worse ergonomics when you want to make things fast or to work in an environment for which garbage collection is a bad fit (e.g. embedded, real-time...), because important decisions like stack vs heap go from being something under your control, to being something under the control of magic compiler optimizers, whose actions can often be hard for humans to comprehend.

I don't think there is a way out of this particular tradeoff, but if V is trying to find one, power to them!

If you want something that always works, use .iter(). The fact that collection references implement IntoIterator (which is what for loops and a few other things expect) is just a convenience shorthand that happens to work in a broad range of scenarios, but cannot and will never be universal.

8 Likes

Maybe I should come clean here. I've been writing a Python to Rust compiler, and I keep tripping up over issues that are basically where Python syntax is clean but slow, and Rust gives lots of options. When you hand-write Rust, you can easily fall into the standard patterns you are used to, but trying to generate, so that it is both human-readable and efficient, is hard.

Yes, I agree about always using .iter() being guaranteed to work. Maybe that's what I should do in my generated code.

In terms of garbage collection, every large-scale project I've worked on has used garbage collection in some form or another, even those written in Rust. I count Rc and Arc as a form of garbage collection. What I'd really like in Rust would be a method of garbage collecting objects that handled circular references, and also that was fast and thread-safe. Rc is fast. Arc is really slow.

1 Like

I remember seeing some experiments towards building tracing garbage collection libraries in Rust, boats' Shifgrethor blog post series comes to mind and searching for "garbage" on crates.io gives a couple of hits too.

Usually, the result of those experiments is too unergonomic for people to actually want to use them in hand-written code, GC is really something whose ergonomics deeply benefit from compiler integration. But if you're generating code, maybe the ergonomics of hand-written code don't matter so much and these libraries would be worth looking into?

1 Like

If you think Arc is slow, I have a hard time imagining you can beat it with garbage collection.

1 Like

I have seen some attempts at a Rust garbage collector using special Gc<...> wrapper objects. I can't see why that wouldn't work well, but the project did not appear to be alive.

The problem with Arc is that it uses atomic operations. These apply a bus lock, which means that every CPU has to block while a read and write operation happens to at least the level of cache shared between all CPUs. This can be really slow. Years ago, I did some profiling of a large program that used shared pointers in C++, and the addition of atomic operations slowed the whole program by 10%.

Modern heaps are much more clever with memory. They try to maintain thread affinity, keeping objects in the same thread which means they can be released and reused without the need for atomic operations (just like Rc in Rust). Then, if they do have to cross thread boundaries, they do have to wait for a garbage collection thread, which will assert a global mutex to prevent heap operations, but at least they are not hammering at the atomic operations over and over, as would happen with Arc.

2 Likes

Atomic operations are for ref counting only, and not for accessing the actual data. Are you frequently cloning/destroying Arcs by any chance (i.e. cloning Arcs on every assignment transpiled from python)? If so, then GC definitely makes sense as a way of amortizing that cost. However, if your transpiler can smartly avoid cloning or even the need for a smart pointer by doing some compile-time ownership analysis, it might result in massive savings while relying on Arc.

3 Likes

My transpiler is still at a pretty early stage, and it doesn't even use Arc/Rc yet, but my plan is to analyse the usage of objects and only use reference counted containers where it is hard to track ownership.

Agreed that Arc should only be cloned where absolutely necessary. That test I was talking about earlier was of a project which used C++ pre-move-semantics, and so ended up incrementing and decrementing counters a lot more than necessary. At least Rust gets that right.

1 Like

No, V-lang looks and feels more like refined Go - lang.... Yet It is still not in release state and its current version - 0.1.24.is about nothing. I mean nothing... to discuss

Actually they've talked about this kind of memory management:
https://aardappel.github.io/lobster/memory_management.html

Personally I prefer a bottom-up approach, build a graph of all function calls and starting from the functions that only call standard library functions or other libraries, you can determine whether or not each variable can be given or if it must be borrowed.So Rust like memory management but automatic.

No way they can keep fast compiles if they do that

Just might work..

That appears to be about a different programming language called Lobster. Is it related to V in some way? (I couldn't find any mention of Lobster on the V site or vice versa)

1 Like

@Ixrec In the V Discord channel, I was told that they were hoping to use the same kind of memory management and given a link to that same article.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.