Live data from Hacker News

Rust's language ergonomics initiative

blog.rust-lang.org

121–130 of 295 posts

Re: Rust's language ergonomics initiative

#122

Earlier quoted context omitted.

#define M_PI 3.14159265358979323846264338327950288

3.141592653589793115997963468544185161590576171875 is the exact decimal representation for the 64-bit IEEE-754 number that's closest to pi (viz. 0x400921FB54442D18). Any time you see a decimal floating-point constant with a nonzero fractional part that doesn't end in '5', you're looking at a bug. EDIT: As long as this grizzled old Fortran programmer is giving out free advice, I'll add two more items every programmer…

The code below works for me

#define PI1 3.141592653589793115997963468544185161590576171875

double pi1 = PI1;

#define PI2 3.14159265358979323846264338327950288

double pi2 = PI2;

assert(pi1 == pi2);

(edit: or even 3.14159265358979323846)

Re: Rust's language ergonomics initiative

#123

Earlier quoted context omitted.

When we're trying to balance a trade off, I often wish we could just do A/B testing on it, but that's not realistic for languages.

What you can do is run over a large corpus of programs (crates.io? GitHub?) to identify the places where the different alternatives would impact code, collect metrics on them, and pull some sample programs to investigate the impact on them of the different alternatives. Is anything like that being done? The HTML5 spec was developed in this way, and some of the code-health folks at Google were just starting to operate…

We use crater to check potentially breaking changes against our entire package ecoystem, but its not as easy to test which of two syntaxes for a new feature will be easier to use by looking at existing code.

Re: Rust's language ergonomics initiative

#124

Earlier quoted context omitted.

3.141592653589793115997963468544185161590576171875 is the exact decimal representation for the 64-bit IEEE-754 number that's closest to pi (viz. 0x400921FB54442D18). Any time you see a decimal floating-point constant with a nonzero fractional part that doesn't end in '5', you're looking at a bug. EDIT: As long as this grizzled old Fortran programmer is giving out free advice, I'll add two more items every programmer…

The code below works for me #define PI1 3.141592653589793115997963468544185161590576171875 double pi1 = PI1; #define PI2 3.14159265358979323846264338327950288 double pi2 = PI2; assert(pi1 == pi2); (edit: or even 3.14159265358979323846)

Your PI2 rounds to PI1 under the rounding mode used at compilation time. Print it out with "%50.48f" (or FORMAT(F50.48)) and you'll see PI1. But PI1 is independent of rounding mode.

Re: Rust's language ergonomics initiative

#125
After writing Rust in production for a while, the biggest bugbear I have is the naming/file structure.

I end up a lot with this;

    src/main.rs
    src/combobulator/mod.rs
    src/combobulator/tests.rs
    src/tests.rs
    src/somethingelse/tests.rs
    src/somethingelse/mod.rs
Because I find tests in the same file a bit confusing. It's really easy with maven-style layouts to know that "only things in main/java or main/scala get compiled and go into the jar". "src/test/*" and "src/main/resources" are for me. The same thing applies for cargo.tomls and resources - there's not really a way to see what goes into the executable from the file structure.

But this isn't the biggest problem with having things called "mod.rs". That would be if I open 5 mod.rs's in a text editor with tabs, I have no idea what goes with what.

I know that tests should go under tests/, but that's specifically for integration tests. Integration tests are an order of magnitude less likely to get written imo, and if they are they'll probably get written as unit tests anyway.

If anyone has any top tips for how to structure larger Rust projects while separating unit tests into different files, please let me know!

Re: Rust's language ergonomics initiative

#126
> Right now, such a signature would be accepted, but if you tried to use any of map’s methods, you’d get an error that K needs to be Hash and Eq, and have to go back and add those bounds. That’s an example of the compiler being pedantic in a way that can interrupt your flow, and doesn’t really add anything; the fact that we’re using K as a hashmap key essentially forces some additional assumptions about the type. But the compiler is making us spell out those assumptions explicitly in the signature.

I feel this exact same way with Go. E.g.

    x := map[string]map[string]int{
        "key": map[string]int{
            "another": 10,
        },
    }
Given that the outer type signature says that the `value` of the map should be a `map[string]int` it's sometimes quite annoying to specify that inner type over again

Re: Rust's language ergonomics initiative

#127
post #112

The implied bound one reminded me of a very similar thing in haskell https://prime.haskell.org/wiki/NoDatatypeContexts . Basically data Hashable a => Set a = ... is completely useless. It only forces you to add constraints to functions that, if necessary, would be required anyway. Not to be confused with existential quantification data ExistentialSet a = forall a . Hashable a => ... which carries a reference to the h…

DatatypeContexts turns on a feature that Rust already has - constraints on type parameters to datatypes. This is about propagating constraints from the datatypes to functions over it.

Haskell hasn't found DatatypeContexts very useful, but Rust has. In my opinion this is largely because of the difference in what our type systems mean - in Rust, types carry a lot more information about the memory model & data layout than in Haskell. This has led to a different skew.

In Haskell, DatatypeContexts also create struggles with higher kinded polymorphism (you can't implement Functor for the definition of Set you just provided, for example), but in Rust, the same memory model concerns that make datatype constraints useful make traits like Functor less useful.

Re: Rust's language ergonomics initiative

#128

Are there plans to do user studies? 10 minutes watching new users code in Rust will give you better ideas than 10 weeks thinking about the problem in your head. I feel like there's a real lack of user testing in software development tools land. If you're developing software for unsophisticated users it's obvious that you should be doing user testing, but it's an often ignored fact that developers are users too! APIs,…

> 10 minutes watching new users code in Rust will give you better ideas than 10 weeks thinking about the problem in your head.

I am not sure whether 10 minutes of Rust would give you actionable info, I mean it certainly takes longer to get familiar with the basics in almost any language, even if the 10 minutes just stands for a short amount of time.

Re: Rust's language ergonomics initiative

#129
post #88

Earlier quoted context omitted.

Rust calls them "structs". They're like classes, but different. Rust also has "traits". They're like abstract classes, but different.

Traits are closer to interfaces than abstract classes, iirc abstract classes can have fields.

I've noticed this and while I don't use it much it has caught me off guard once or twice. And while it wasn't the end of the world, I wasn't too fond of the solutions I came up with. Is there a reason why they can't have fields? Why wouldn't they just be an "extension" to a struct/enum, modifying their memory representation?

Re: Rust's language ergonomics initiative

#130
post #121

I was able to work with some rust developers at Hack Illinois recently. We started the 2017 Rust cookbook [0] with Brian Anderson. [0]: https://github.com/brson/rust-cookbook

Very cool! Took me a while to find the rendered version, though: https://brson.github.io/rust-cookbook/
Post reply on HN