Hacker News new | ask | show | jobs
by ainar-g 2230 days ago
One way to reason about what could have been done better from the beginning is looking at stuff that is marked as [deprecated] in the standard library. E.g. how the "try!()" macro was deprecated in favour of the "?" operator.
3 comments

I would say the try!() macro is an exception to that rule: if the ? operator existed since the beginning, it would be seen as "too much magic" (in a language that already used up most of its "strangeness budget" in lifetimes/borrowing), while try!() is just a very simple macro you could write yourself, with no special compiler support. Only later, after people got used to try!() everywhere, the ? operator became viable, as "just a shortcut to try!() with better precedence (and it also works on Option)".

That is, there's a path dependence, where the existence of try!() made the ? operator viable.

>if the ? operator existed since the beginning, it would be seen as "too much magic" [...] That is, there's a path dependence, where the existence of try!() made the ? operator viable.

Yes, C++ creator Bjarne Stroustrup made a similar observation:

- For new features, people insist on LOUD explicit syntax.

- For established features, people want terse notation.

There seems to be an invisible "Overton Window" of evolving programming language features and syntax.

Having both the terse and the verbose is so valuable for onboarding.

I feel like the reason pointers as a mechanism in native languages is such a barrier to cross for a newbie is because they are this magical star symbol * just floating around doing... something?

If people started out writing pointer<string> foo instead of string* foo and had to use explicit derefrencing via name rather than by magical glyphs onboarding would be so much easier.

I think it applies to almost all programming concepts too. Starting a language with a baseline grammar of just function invocation -f(x) = y as <noun>.<verb>(<noun>...) - and extrapolating from there and introducing terse grammar progressively as shortcuts would serve much better to get concepts in heads rather than arcane ritualistic glyphs. Introduce x.add(y) then say x + y is the shorthand.

Rust does a really great job "functionizing" almost everything in the language - it has the add trait after all https://doc.rust-lang.org/std/ops/trait.Add.html. You can actually write tons of Rust in just function call form and make it look like Lisp.

I think more interesting would be something we're truly stuck with (at least until Rust 2.0, which may never come).
(Stuff that’s deprecated in the standard library is stuff we’re stuck with; they cannot be removed in editions.)
I've seen this said many times, but I don't really understand why.

Why couldn't a new Rust edition create a new std2021 (for instance), and automagically use it when importing a std submodule in a project using the new edition (and in the prelude)? The old implementation would still be imported using std in crates using prior edition, and could still be imported in the new edition, but named std2018.

If all the implementation (except the now deleted stuff) is put in the std2021 module and the old std2018 () simply re-export it (and re-implement the old stuff), you wouldn't break anything would you?

I'm probably missing something, but so far I don't know what and I'd be really happy if somebody enlightened me.

> Why couldn't

There may be possible ways of doing this, but you're approaching this from the wrong angle. Right now, this is not possible, due to policy. This policy is informed by the technical restrictions right now. There may be possible ways in the future to handle this, but as of right now, there are not.

The reason this is true right now is that there is one copy of the standard library for every program. So it needs to support all editions, because code from multiple editions may call standard library functions.

If we had multiple copies of the standard library, you may end up with issues where two different programs can't interoperate because they'd be using different versions of the same crate, and given that one of the most important features of the standard library is interoperation, this is a huge drawback for the stdlib specifically.

(There may be other technical issues, I am not an expert here, but that's the biggest hurdle as far as I know.)

This isn't the answer I wanted, but it's a good answer. Thank you
You’re welcome. (I imagine that you’d get the same version conflict situation with your idea btw: std::2018::Option is not the same type as std::2021::Option.)
Sure but you don't have to use them, is the point I'm trying to make. They don't affect modern code and while it's annoying they are used in older code there is at least a path forward to "upgrade" the code to the modern equivalents.
Could a lint check for them and warn if some code uses them?

This way slowly the ecosystem could move and stuff could be eventually removed.

If you use something that's deprecated, you get a warning, yes.

> could be eventually removed.

It can not be used according to our stability policy. There's a lot of closed source Rust out there.

There has been talk on the internals forum of "gating" deprecated parts of the std on a new edition. So the deprecated feature will be hidden for crates that declare `edition = '2030'` but will be available for crates using an older edition. Essentially turning the warning into an error.

But this is just talk at the moment. Currently there is no mechanism to implement this. It would also be a challenge for documentation.

Yes; this is so far off, and is not even at the RFC stage, that I didn't mention it. But you're right that maybe, someday, we could make it even harder for folks to call these things in newer editions.
No, this was intentional. The point was to see how the user base used the language before adding permanent language features.