Live data from Hacker News

An incoherent Rust

boxyuwu.blog

91–100 of 175 posts

Re: An incoherent Rust

#91
post #83

I feel like encapsulation and composition are in strong tension, and this is one place where it boils over. I've written a decent bit of Rust, and am currently messing around with Zig. So the comparison is pretty fresh on my mind: In Rust, you can have private fields. In Zig all fields are public. The consequences are pretty well shown with how they print structs: In Rust, you derive Debug, which is a macro that impl…

> so if the API is bad, you're pretty screwed. Is this really that big a downside? It encourages good APIs. The alternative of everything being public is the kind of feature that quickly becomes a big disadvantage in larger systems and teams, where saying “just don’t footgun yourself” is not a viable strategy. If there’s a workaround to achieve some goal, people will use it, and you end up with an unmaintainable mess…

There are always corner cases where you might need to do something differently. I had three memorable cases in my career: 1. Python 2.6x had a a stdlib bug where windows event logging did crash the process when the user had some rights set differently. Fix submitted but for the meantime we simply overwrote the private function and could ship. 2. Also python: scikit-learn had a primitive "print everything" strategy, but we need to get it into a logging framework. We overwrote their print wrapper and could ship. 3. In C#, a third party lib insisted on dumping a result to a file. We used reflection to get that as a stream.

All three are not ideal - but I think having escape hatches is important. I also think private/public is overrated. Having it as a signal is ok. Forbidding access to privates is too strong.

Re: An incoherent Rust

#92

Earlier quoted context omitted.

I'm not sure what you're getting at but const bool z = (const bool)((int8_t)2); Is perfectly valid C++.

That's a conversion, not the same. The naive equivalent to transmute would be int8_t x = 2; bool y = *reinterpret_cast (&x); But reinterpret_cast isn't valid in a constexpr scope.

My point is, in your exact example both reinterpret_cast and C-style casts have the exact same behavior, making the example bad. If you want to showcase a deficiency of C++, it would make sense to pick something where the difference between cast types actually matters.

Re: An incoherent Rust

#93
post #15

This is one of the (several?) things that make me very worried about Rust long-term. I love the language, and reach for it even when it sometimes isn't the most appropriate thing. But reading some of the made-up syntax in the "Removing Coherence" section makes my head hurt. When I used to write Scala, I accepted the fact that I don't have a background in type/set/etc. theory, and that there were some facets of the la…

> I wonder if C++ has some hairy concepts and syntax today on par with Rust's more difficult parts. … … … … Unqualified name lookup has been challenging in C++ since even before C++11. Overload resolution rules are so painful that it took me weeks to review a patch simply because I had to back out of trying to make sense of the rules in the standard. There's several slightly different definitions of initialization. I…

The right strategy to use C++ efficiently is to set warnings to the maximum as errors and take the core guidelines or similar and avoid past cruft.

More often than not (except if you inherit codebases but clang has a modernize tool) most of the cruft is either avoidable or caught by analyzers. Not all.

But overall, I feel that C++ is still one of the most competitive languages if you use it as I said and with a sane build system and package manager.

Re: An incoherent Rust

#94

Earlier quoted context omitted.

> starting playing around with std::launder and std::byte and strict aliasing rules and lifetime rules, and you'll yearn for the simplicity of Rust Annotations like std::launder, lifetime manipulation, etc solve a class of problems that exist in every systems language. They inform the compiler of properties that cannot be known by analyzing the code. Rust isn't special in this regard, it has the same issues. Without…

> Rust isn't special in this regard, it has the same issues. This is both fundamentally true and misleading. Rust has to solve the same issues but isn't obliged to make all the same bad choices to do that and so the results are much better. For example C++ dare not perform compile time transmutations so, it just forbids them and a whole bunch of extra stuff landed to work around that, but in Rust they're actually fin…

In my experience conversions is one of the things that maximum warning levels do excellent static analysis for nowadays. In the last 15 years I hardly had a couole problems (init vs paren initialization). All narrowing etc. is caught out of the box with warnings.

Re: An incoherent Rust

#95

I used Rust for ~14 months and released one profitable SaaS product built entirely in Rust (actix-web, sqlx, askama). I won't be using Rust moving forward. I do like the language but it's complicated (hard to hold in your head). I feel useless without the LSP and I don't like how taxing the compiler and LSP are on my system. It feels really wasteful to burn CPU and spin up fans every time I save a file. I find it har…

> It feels really wasteful to burn CPU and spin up fans every time I save a file. I find it hard to justify using 30+ GB of memory to run an LSP and compiler.

Have you tried using RustRover. I've never seen it go above 2-3GiB of RAM, but I don't write the most complex of software in Rust.

> I hate how crates.io requires a GitHub account to publish anything.

You don't need Github account to publish iirc, you need it to authorize to crates.io. You can use any Git host, but your account is tied to GitHub.

Re: An incoherent Rust

#96

Earlier quoted context omitted.

It's much simpler and better than it used to be but it's still pretty bad. As just one example off the top of my head consider the meaning of curly braces for initialization. There's several different things they can mean depending on the context. Good luck figuring out which set is currently in effect.

Use static analyzers and move on. Almost all the complaints I see about C++ nowadays are removed by max warning levels. Set them as error. Certainly initialization is the single most confusing feature in C++, I can give you that. But still doable with s few patterns to remember. And warnings always max level.

I still use Eclipse CDT and its static analysis is running in real time, as you type code, which is killer. Combined with Valgrind integration, I don't see myself moving on anytime soon.

Re: An incoherent Rust

#97

Earlier quoted context omitted.

Other than duck-typed languages (and I count Go as basically that), which languages actually provide this feature? AFAIK, it’s not really very common to be able to extend foreign types with new interfaces, especially not if you own neither. C++ can technically do it using partial specialization, but it’s not exactly nice, and results in UB via ODR violation when it goes wrong (say you have two implementations of a `s…

C# isnt a duck type language (well, you can do that via dynamic keyword, but I don't know who would do that typically). Most integration libraries in Nuget (aka c#'s cargo) are AB type libraries. E.g. DI Container: Autofac Messaging Library: MediatR Integration: MediatR.Extensions.Autofac.DependencyInjection There are many examples of popular libraries like this in that world.

C# does not support adding interfaces to foreign types. It does support extension classes to add methods and properties to a type, but nothing that adds fields or changes the list of interfaces implemented by a type. Rust supports this as well, because you can use traits this way.

Dependency injection is a popular solution for this problem, and you can do that as well in Rust. It requires (again) that the API is designed for dependency injection, and instead of interfaces and is-a relationships, you now have "factories" producing the implementation.

Re: An incoherent Rust

#98
post #78

Earlier quoted context omitted.

Other than duck-typed languages (and I count Go as basically that), which languages actually provide this feature? AFAIK, it’s not really very common to be able to extend foreign types with new interfaces, especially not if you own neither. C++ can technically do it using partial specialization, but it’s not exactly nice, and results in UB via ODR violation when it goes wrong (say you have two implementations of a `s…

> Other than duck-typed languages (and I count Go as basically that), which languages actually provide this feature? There are only like 3 significant languages with trait-based generics, and both the other ones have some way of providing orphan instances (Haskell by requiring a flag, Scala by not having a coherence requirement at all and relying on you getting it right, which turns out to work out pretty well in pra…

Sure, the `chrono` library in Rust had essentially the same problem.

Scala is interesting. How do they resolve conflicts?

Re: An incoherent Rust

#99

Earlier quoted context omitted.

I mean… Sure, if we’re just making stuff up, a compiler that can magically understand whatever you were trying to do and then do that instead of what you wrote, I guess that’s a nice fantasy? But out here on this miserable old Earth I happen to think that Rust’s errors are pretty great. They’re usually catching things I didn’t actually intend to do, rather than preventing me from doing those things.

> But out here on this miserable old Earth I happen to think that Rust’s errors are pretty great. They’re usually catching things I didn’t actually intend to do, rather than preventing me from doing those things. As it happens, you are replying to the person who made Rust's errors great! (it wasn't just them of course, but they did a lot of it)

I bow to them and thank them for their service!

Re: An incoherent Rust

#100

Earlier quoted context omitted.

I'm not sure what you're getting at but const bool z = (const bool)((int8_t)2); Is perfectly valid C++.

That's a conversion, not the same. The naive equivalent to transmute would be int8_t x = 2; bool y = *reinterpret_cast (&x); But reinterpret_cast isn't valid in a constexpr scope.

> But reinterpret_cast isn't valid in a constexpr scope.

std::bit_cast is

Post reply on HN