Live data from Hacker News

Rust 1.45

blog.rust-lang.org

161–170 of 227 posts

Re: Rust 1.45

#161

Earlier quoted context omitted.

For those not in the know, computer controlled Civs would be assigned behaviour attributes based on historical personality. Each attribute would be 1-10, stored in an 8 bit integer. These attributes change in response to events in the game. When a civilization would reach the modern era, it's aggression attribute would be reduced by 2. Gandhi's aggression was reduced from 1 to 255 (underflow). He would rain down nuke…

It's a cool story, but I don't think there is evidence that it actually happened (in Civ 1, certainly in later games as a homage to this potentially urban legend). The YouTube channel People Make Games did an investigation[1] about this a year ago, including interviews with the original developers. [1] https://www.youtube.com/watch?v=Ur3SdgkW8W4

TIL that I am fake news.

Re: Rust 1.45

#162

As someone who hasn't used Rust, I am curious about why Rust has macros. I use C++ at work, which admittedly isn't the language I use most, and macros are used quite a bit in the code base. I find they just make the code harder to read, reason about, debug, and sometimes even write. I don't see them really living up to their claimed value. Is there something different about Rust's macros that make them better?

The first thing I would say is that regular inline macros are hygienic and type safe, just like the rest of the code you write. That way they're not just text expansion but smart code expansion.

When I say hygienic, I mean that when a macro uses a variable that isn't in the parameters or isn't static, it will be a compile error as it cannot know the scope. Any variables defined inside are scoped. Only parameters parses in can be referenced from outside the scope of the macro

They're also notated different to regular functions and they can't appear anywhere so it's obvious when you see a macro that it will expand into some code that won't break any of the other code in your function.

Of course people can write really terrible macros but typically macros serve a single very simple task and should be well documented and in my experience they often are.

As for procedural macros. They are just ast in, ast out functions, but written as a library in regular rust rather than some language thrown on top. That makes it easy to reason about the code and make it safe. If you write them well, they can be very good at reporting errors in usage to users.

The std lib also provides some very straightforward yet useful macros to act as inspiration. String formatting is an inline macro. vec is a macro to quickly define Vectors. Derive debug, partial equality, default values are all procedural macros and they are very straightforward yet tedious tasks to do on your own all the time.

Given the macros people publish, I would say they've done a good job at securing them as a useful feature. I've not seen many instances in actual code bases of messy macros. For examples of great macros, see serde[0], clap[1], inline-python[2]

[0]: https://github.com/serde-rs/serde [1]: https://github.com/clap-rs/clap [2]: https://docs.rs/inline-python/0.5.3/inline_python/

Re: Rust 1.45

#163

Earlier quoted context omitted.

>= 1.0 in semantic versioning universally means that it should be "stable enough"

The Rust ecosystem typically has much more conservative version numbers than other ecosystems though, and higher quality standards. There are several very high quality crates with 0.x version numbers.

They are doing it wrong then.

Re: Rust 1.45

#164
post #149

As someone who hasn't used Rust, I am curious about why Rust has macros. I use C++ at work, which admittedly isn't the language I use most, and macros are used quite a bit in the code base. I find they just make the code harder to read, reason about, debug, and sometimes even write. I don't see them really living up to their claimed value. Is there something different about Rust's macros that make them better?

Writing macros (in any language) is a way of creating an abstraction. Creating abstractions is a way of automating the job of programming, making it ideally more efficient and less error prone. This is why people usually prefer java to basic. Marcos are a way of creating abstractions that are particular suited to be "concreted" by the compiler, making them a ideal match for programming languages that seek to be "clos…

> C Macros are lacking because they are very primitive, e.g. they have not type system. They are also hardly turing complete. Its extremely hard to write a meaningful algorithm in them.

I think this may be why I'm having a hard time appreciating them. Probably half the macros I see could just be a function call. The majority of those that don't are hiding a conditional return or goto, which I find to be a net negative.

I'll probably have to use a language with good macros before I can appreciate them.

Re: Rust 1.45

#165
post #35

Earlier quoted context omitted.

IMHO, it's a shame So Much time has been spent (~3 years ?) on async at the cost of basic features like multipart and CORS. But I understand it could be more fun for the devs :-)

I think it makes sense to get your foundation and ergonomics correct before piling on features. Otherwise you end up building features that may need to be completely restructured/redone later.

[deleted]

Re: Rust 1.45

#166

Earlier quoted context omitted.

`as` is not considered idiomatic in Rust code,. `.into()` for infallible cases and `.try_into()` for fallible cases are preferred in almost all cases (in the case of floats there's still discussion around the correct behavior of `.try_into()` for edge cases). > So I think this is again an example of rust making a decision that hurts program correctness. Could you expand on other examples?

> `as` is not considered idiomatic in Rust code Yes it is. It's used all the time . There's a reason as_conversions defaults to Allow in clippy. Of course, there are lots of situations where `as` is the wrong tool for the job, but I think it's a bit of a stretch to call `as` "not idiomatic". It's perfectly idiomatic in lots of situations. Whether or not it should be idiomatic is a separate question.

I think the parent poster is jumping the gun, but it is true that the flaws in `as` have been acknowledged for a long time and alternatives for specific use cases have been regularly introduced in order to reduce its use where possible. Giving it dedicated syntax might be one of the bigger warts of Rust 1.0: it may be the most convenient way to cast between primitive types, but it's often not the best way.

IOW, is it currently unidiomatic? No, code reviewers won't generally look sideways at it. But it's certainly getting less idiomatic over time, and that trend doesn't seem likely to stop soon.

Re: Rust 1.45

#168
post #102

Earlier quoted context omitted.

Compilers are better at eliding array index checks than about eliding numeric overflow checks; an ordinary function that operates on arrays will often be able to reasonably determine both the length of the array and the scope of the indexing variable (Rust's iterators are very good at this), whereas an ordinary math function often has almost no information that usefully limits which values it might be getting called…

They aren't unforgiving, because if you need performance you can use another function that does not do the check. Same as for arrays. It seems strange to have a cast as a safe operation and yet return results that are almost surely a bug. This means I will avoid casts altogether in my code, and I do hope they get rid of them at some point as some have suggested.

> They aren't unforgiving, because if you need performance you can use another function that does not do the check

Rust tries hard not to cause regressions in users without good cause, which includes avoiding runtime performance regressions. One of the reasons that this fix took so long was that benchmarking prospective solutions revealed unacceptable performance regressions in users, even those who were already "doing the right thing" by manually upholding the proper invariants (no NaN, and value within range). The tension is that something still needed to be done, because at the end of the day the Rust creed is still "no undefined behavior without `unsafe`".

> This means I will avoid casts altogether in my code

Indeed, this is hardly discouraged wherever possible. For converting, say, a u64 to a u8, use `foo.try_into()` in order to get a conversion that follows the usual Rust conventions around Result-based error-handling (which didn't exist back when `as` was first conceived, or when this bug was originally filed). Casting floating point types to integers is already a rather rare use case in the first place.

Re: Rust 1.45

#169
post #87

Earlier quoted context omitted.

I'm not sure I understand this. Does it not produce a run time error? Why not? This looks very dangerous, because it essentially does the "nearest to right" thing. Say, you cast 256 to a u8, it's then saturated to 255. That's almost right, and a result might be wrong only by 0.5%. Much harder to detect than if it is set to 0.

> Why not? For better or worse, Rust 1.0 released with the philosophy that the `as` operator is for "fast and loose" conversions where accuracy is not prioritized; e.g. casting a u32 to a u8 would always risk silently truncating in the event the value was too large to represent. Over the years the language has added a lot of standard library support for bypassing the `as` operator entirely, and I think the prevailing…

It seems to me (FWIW as someone curious abt Rust but not seriously using it yet), that "as" should require a warning label. If "unsafe" means something else, then "unsound" could be used. If the types are always safe to convert, "as" is fine, but if the types involved allow for a lossy conversion in any case, the compiler would require you to write "unsound as". You are both acknowledging that you are aware of the issue and notifying future users of that code of a potential problem. Rust could go ahead with the saturating conversion to remove the UB AND require the "unsound" warning label.

If required to an an "unsound" label, that might be enough push for some developers to add their own explicit "if" guards or use another conversion method without having to deprecate "as".

Re: Rust 1.45

#170
post #87

Earlier quoted context omitted.

> Why not? For better or worse, Rust 1.0 released with the philosophy that the `as` operator is for "fast and loose" conversions where accuracy is not prioritized; e.g. casting a u32 to a u8 would always risk silently truncating in the event the value was too large to represent. Over the years the language has added a lot of standard library support for bypassing the `as` operator entirely, and I think the prevailing…

Should `as` then be a candidate for deprecation in the next edition?

I don't know about the next edition; `as` is also used for a small number of non-numeric conversions, like turning a reference into a raw pointer or for creating a trait object. In order to completely remove `as`, you would need to first introduce alternatives to those (the trait object use case specifically might be a bit weird as a method rather than a keyword, but I don't know if that's a big problem).

Alternatively one could just deprecate `as` for numeric conversions, although there are still some library holes that would need to be patched up (e.g. other than `as` I don't know of an existing single method to say that you want a fast integer conversion routine that merely truncates a u64 into a u32; right now the alternative is `try_into`, which does a runtime check and returns a Result). It might also exacerbate tensions with some people who for quite a while have been grumpy that Rust requires frequent explicit numeric conversions when doing things like indexing (which always requires a `usize` type, so you see `foo[bar as usize]` unless people want to always work with usizes directly); would these people be happier if that were `foo[bar.as_usize()]` instead, or would this all be blocked on a discussion about being more lenient with numeric conversions?

Post reply on HN