Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> > What IS the idiomatic Rust way to do a cyclical directed graph?

> Unfortunately, the correct idiomatic way is that you try very hard to avoid doing so. Rust is all about clear ownership, and it doesn't like circular references.

> The usual solution is to put the cyclic graph code into a library, and to use pointers and about 20 lines of unsafe code.

The point about C++ is important. Cyclic graphs are hard in any non-GC'ed language because it breaks the ownership story.



The usual solution is to put the cyclic graph code into a library, and to use pointers and about 20 lines of unsafe code.

That indicates a fundamental design flaw in the language.


In what conceivable way?

Safe Rust allows one to do an incredible amount of things whole providing strong guarantees against the sorts of problems that plague lower level languages. Since this isn't suitable for absolutely everything, we have unsafe Rust to fill in the gaps in the small areas it's needed. Unsafe Rust isn't "bad", it just doesn't provide the same guarantees as safe Rust. And if something goes wrong, you can at least narrow down your search to unsafe areas of the code.

This isn't the sign of fundamental language design flaws. It's the sign of a phenomenally well-designed language, where the downsides of seldom-needed yet powerful features are limited to only those areas where they're used.


I'm not convinced that cyclic data structures are a feature that's exotic enough to warrant breaking the language contracts. This thread alone shows that it's a common occurrence in tree structures. There will be likely be other structures as well.

So I'd think a better way than saying "don't do that - or if you have to, you're on your own" would be to analyze use cases and see which scenarios the language can satisfy. (As another poster suggested in making "parent pointers" an explicit language feature(


Agree. The language's memory safety system needs to support more common use cases. At least:

- Back pointers. (They're not owning pointers, and they have a well defined relationship with some other pointer. The language may need some way to explicitly say that.)

- Collections where not all slots are initialized. (This requires simple proofs by induction as you grow a collection into previously allocated unused space.)


You can always use std::rc::Weak if you need a cyclic data structure with weak references. That covers, I suspect, the majority of the use-cases for these type of structures.

For real, honest-to-god, cyclic data structures — just use unsafe Rust. Again, unsafe Rust isn't "bad". It's just unsafe. More care will be expected of the code to ensure that it exports a safe interface, but nothing in the language stops you from doing it. There's quite literally no loss of expressive power.


And if something goes wrong, you can at least narrow down your search to unsafe areas of the code.

No. That's only true if the unsafe code presents a completely safe interface to its callers. If the safe code opens a hole in Rust's protection system, which is very easy to do, you can now have C-type no-idea-where-it-is bugs.


But the origin of the bug is still certainly in the unsafe areas.


Yes, the crash can come from every line of code, but the origin of the bug is in the unsafe code. That's why unsafe code has to be cleanly inspected to be sure it has a safe interface, and by reducing the dangerous area to only few lines, it is far easier to do.


All languages have design flaws. Thats why people keep making new languages. Arguing that Rust does not have design flaws is going to arouse more skepticism then anything else.

It is not mandated that you 'must' write safe code but that you 'can' write safe code. So there really is no fundamental assurance that rust and its libraries are in fact 'safe' by Rusts own definition in any meaningful sense.

You could make the same style argument that C is a 'safe' memory language also as long as you use automatic memory management and no malloc. Of course that would be a rather disingenuous claim to make.


Nobody's arguing that Rust doesn't have design flaws.

That said, people also need to understand that many such instances are not design flaw, but are instead design tradeoffs. The OP indicated that having to switch to unsafe Rust to represent a cyclic datastructure is a design flaw. My response is that it's a tradeoff that pays dividends in every other piece of code.

Can Rust improve upon the number of problems that can be solved with safe vs. unsafe Rust? Absolutely! Is it worth cordoning off a few cases that don't technically need unsafe behavior, to ensure all other Rust code performs safely? Emphatically yes.


> All languages have design flaws. Thats why people keep making new languages. Arguing that Rust does not have design flaws is going to arouse more skepticism then anything else.

As somebody who has used Rust since late 2012, I completely agree. It seems that most of the more sweeping claims come from those new and excited users - hopefully over time this will soften and become more reasonable. Hype is definitely something that needs to be kept in check though, as it more than often results in a back-fire.


The fundamental flaw being the lack of a GC?


You write your cyclical graph implementation many times less than the implementation is used. The majority of the code need not deal with it.


No it doesn't.

It indicates that idiomatic Rust doesn't like cyclic references and thus you must step outside safe, idiomatic Rust to do that, it really just means that every language has an idiomatic way to do things to stay on that idiomatic road and not every way of doing things fits the idioms - they're still possible but not idiomatic. Given how the ownership system works, it makes sense

You may say that that indicates a flaw in the ownership system, but it doesn't. The ownership system can do certain things, but not all of them - it's designed to prevent the majority of common memory safety violations, but if it can't prove everything. That doesn't indicate a design flaw, it indicates a system limitation, same way a GC pause it's not a design flaw, but rather a limitation of a well deigned system.


Which flaw does it indicate? It seems like there is nothing about the solution that contravenes the design goals of the language.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: