9 ms·
Automatically deriving Clone is a convenience. You can and should write your own implementation for Clone whenever you need it and automatically derived impleme
by loa_in_ 1y ago
Automatically deriving Clone is a convenience. You can and should write your own implementation for Clone whenever you need it and automatically derived implementation is insufficient.
- josephg 1y agoBut this issue makes it confusing & surprising when an automatically derived clone is sufficient and when its not. Its a silly extra rule that you have to memorise. By the way, this issue also affects all of the other derivable traits in std - including PartialEq, Debug and others. Manually deriving all this stuff - especially Debug - is needless pain. Especially as your structs change and you need to (or forget to) maintain all this stuff. Elegant software is measured in the number of lines of code you didn't need to write.
- 0rzech 1y agoIt's surprising up to the moment the compilation error tells you that all of the members have to implement derived trait. Nevertheless, it would be cool to be able to add #[noderive(Trait)] or something to a field not to be included in automatic trait implementation. Especially that sometimes foreign types do not implement some traits and one has to implement lots of boilerplate just to ignore fields of those types. I know of Derivative crate [1], but it's yet another dependency in an increasingly NPM-like dependency tree of a modern Rust project. All in all, I resort to manual trait implementations when needed, just as GP. [1] https://crates.io/crates/derivative https://crates.io/crates/derivative
- 0rzech 1y agoApparently, Derivative is unmaintained [1], but there is Derive_more [2], Educe [3] and Derive-where [4], if anyone is interested. [1] https://rustsec.org/advisories/RUSTSEC-2024-0388.html https://rustsec.org/advisories/RUSTSEC-2024-0388.html [2] https://crates.io/crates/derive_more https://crates.io/crates/derive_more [3] https://crates.io/crates/educe https://crates.io/crates/educe [4] https://crates.io/crates/derive-where https://crates.io/crates/derive-where
- josephg 1y ago> It's surprising up to the moment the compilation error tells you … Unfortunately this problem only shows up when you’re combining derive with certain generic parameters for the first time. The first time I saw this, I thought the mistake was mine. It was so surprising and confusing that it took half an hour to figure out what the problem was. I thought it was a compiler bug for awhile and went to file it on the rust project - only to find lots of people had beat me to it. Aside from anything else, it’d be great if rust had better error messages when you run into this issue.
- duped 1y agoIt took you 30 minutes to understand what "could not call Clone::clone because <type> does not satisfy Clone" means?The error message tells you exactly what the problem is and how to fix it. This is a pet peeve of mine so I'm sorry to be overly dismissive. There are bad error messages out there in the world that are impossible to parse, but this is not one of them. Trying to file a github issue before attempting to understand the error message is insane to me.
- josephg 1y agoYes it took me 30 minutes. The error message in this case is uncharacteristically bad. Or I found it particularly confusing because of quirks in my understanding of rust’s type system. Take a look. Do you think this quirk of derive is obvious from the error message alone? Would you have figured it out, in the context of a much more complex program with dozens of other changes that may or may not have been related? https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f4c0d2a1e93fc80487c8708782d10210 https://play.rust-lang.org/?version=stable&mode=debug&editio... The compiler error says my type didn’t implement clone. But #[derive(Clone)] was right there on my type, and my type was obviously cloneable. The error wasn’t on the derive - or anywhere nearby. My program even compiled successfully, right up until I tried to actually call clone() on my object. And my type trivially, obviously was cloneable because all the fields were clonable. My first thought at the time was that my derive attribute was being ignored by the compiler somehow, but it wasn’t at all obvious why. The compiler’s suggested fix was also wrong and misleading. It suggests adding clone to an irrelevant type that shouldn’t impl clone in the first place. That’s the wrong fix. In summary, the error message doesn’t offer the real problem, which is that the trait bounds added by derive Clone were wrong. And it didn’t suggest the proper fix - which was to impl clone manually. I was very confused for a good while with this one. Get pissy if you want but I find this incredibly counterintuitive and I found the compiler’s error message to be uncharacteristically unhelpful. If this quirk of derive was truly obvious, this blog post wouldn’t have hit the front page of HN in the first place. I cut my hand on one of rust’s sharp edges. Don’t get mad at me for bleeding a little.
- atoav 1y agoThe same is true for memory allocation. But I do not think it makes sense that everybody has to write memory allocators from scratch because a few special cases require it.
- j-pb 1y agoI disagree; Elegant software is explicit. Tbh I wouldn't mind if we got rid of derives tomorrow. Given the ability of LLMs to generate and maintain all that boilerplate for you, I don't see a reason for having "barely enough smarts" heuristic solutions to this. I rather have a simple and explicit language with a bit more typing, than a perl that tries to include 10.000 convenience hacks. (Something like Uiua is ok too, but their tacitness comes from simplicity not convenience.) Debug is a great example for this. Is derived debug convenient? Sure. Does it produce good error messages? No. How could it? Only you know what fields are important and how they should be presented. (maybe convert the binary fields to hex, or display the bitset as a bit matrix) We're leaving so much elegance and beauty in software engineering on the table, just because we're lazy.
- zwnow 1y agoI am sorry but Uiua and LLM generated code? This has to be a shitpost
- Intermernet 1y agoWelcome to the new normal. Love it or hate it, there are now a bunch of devs who use LLMs for basically everything. Some are producing good stuff, but I worry that many don't understand the subtleties of the code they're shipping.
- j-pb 1y agoFor me the thing that convinced me was the ability to write so much more documentation, specification, tests and formal verification stuff than I could before, that the LLM basically has no choice but to build the right thing. OpenAIs Codex model is also ridiculously capable compared to everything else, which helps a lot.
- josephg 1y agoI’ve never tried to use it for formal verification. Does it work well for that? Is it smart enough to fix formal verification errors? The place this approach falls down for me is in refactoring. Sure, you can get chatgpt to help you write a big program. But when I work like that, I don’t have the sort of insights needed to simplify the program and make it more elegant. Or if I missed some crucial feature that requires some of the code to be rewritten, chatgpt isn’t anywhere near as helpful. Especially if I don’t understand the code as well as I would have if I authored it from scratch myself.
- jhugo 1y ago> Elegant software is measured in the number of lines of code you didn't need to write. Strong disagree. Elegant software is easy to understand when read, without extraneous design elements, but can easily have greater or fewer lines of code than an inelegant solution.
- josephg 1y agoSure, I generally agree. But you must admit, that description loses a bit of poetry. I think software - like mathematics - becomes more elegant & beautiful when we find ways to simplify it without making it worse in other ways. Minimising the number of lines of code isn’t the goal. But sometimes making something smaller also makes it easier to understand and sometimes even more powerful at the same time. Those are the days I live for. Alan Kay says the right point of view is worth 50 IQ points. There are plenty of examples of this in software. Innovations in ways of structuring our programs that make them at once simpler and more beautiful. All without sacrificing anything important in the process. We take them for granted now, but innovation is rarely obvious from the outset. Compilers and high level languages. Sum types. Operating systems. Maybe SQL and ECS. Sinatra’s http handler API. And so on.
- eqvinox 1y agoThe entirety of any programming language is a convenience. You could just write your code in assembly; I don't think your argument is "automatic". Question is, how much does this particular convenience matter? The fact that people are writing blog posts and opening bugs about it (and others in the comments here recount running into the issue) seems to indicate this particular convenience matters.
- benreesman 1y agoHaskell/GHC gets this right without any hand-wringing and about 3-4x the practical historical burden and without relying on the runtime. The Rust community is very adamant as a general thing that "you're holding it wrong" when people complain about e.g. BDSM passing semantics, but it's also got REIR/RIIR, which is kinda like "you're holding it wrong" for programming. These two things together are a category error.
- fn-mote 1y agoBy RIIR you mean “Rewrite it in Rust”? I looked it up because I was hoping to get something more substantive from the post, but that’s all I could find.
- benreesman 1y agoYeah, or "Rewrite Everything in Rust". The degree of transparency you'll get on this varies between like Reddit and some Discord server, but it's fairly common knowledge that the Rust community leadership regards all other programming languages as existing in an adversarial, finite-sum outcome space with any remotely adjacent programming languages and regard it's elimination of other language use as a first-order good. Whether this is a first order good because Rust's choices about how to split the difference between C++ and Haskell are in fact the best future for software or because they make all the money from Rust jobs and books and teaching and shit is one of those assume good intentions by default but also pay attention to conflicts of interest scenarios. Speaking for myself I think most of the zeal is legitimate with a few people trying to cash in like you get with any community. But like all philosophies of the "There is One True Way, All Else Must Conform" stripe (in Christianity this is Opus Dei and things like that, in Islam it's called Takfir, it's not a new thing) it's misguided and destructive no matter how genuine the intentions of the hardliners. edit: people will try to say that I'm uniquely antagonistic to Rust, but I opened the meme bookmark tab for a diff and saw this within like two minutes of writing my comment, it's a known thing: https://impurepics.com/posts/2023-03-24-refactoring.html https://impurepics.com/posts/2023-03-24-refactoring.html
- 1y ago