Live data from Hacker News

Dave Herman’s contributions to Rust

brson.github.io

61–70 of 174 posts

Re: Dave Herman’s contributions to Rust

#61
post #54

Earlier quoted context omitted.

I feel like making one more note. I said that “mutable references” was a misnomer and that it’s actually about unique references, but even that’s a bit of a misnomer, because it’s not quite about uniqueness, but uniqueness of access . You can have multiple &mut borrows to the same thing, but only one of them is accessible at any given time: let mut x = 1; let y = &mut x; let z = &mut *y; *z += 1; *y += 1; assert_eq!(…

Would this have worked pre-NLL?

The pre-NLL version would need some additional scopes. In some ways the current borrow-checker is a lot friendlier (there are also some things possible today that weren't before) but it was also a simpler time, where one could easily imagine the various lifetimes. Getting started with the language was harder, but I think internalizing the borrow-checker was easier, because the rules were simpler and you were forced to learn them for anything more complex than 'hello world'.

    let mut x = 1;
    {
        let y = &mut x;
        {
            let z = &mut *y;
            *z += 1;
        }
        *y += 1;
    }
    assert_eq!(x, 3);

Re: Dave Herman’s contributions to Rust

#62
post #61
post #54

Earlier quoted context omitted.

Would this have worked pre-NLL?

The pre-NLL version would need some additional scopes. In some ways the current borrow-checker is a lot friendlier (there are also some things possible today that weren't before) but it was also a simpler time, where one could easily imagine the various lifetimes. Getting started with the language was harder, but I think internalizing the borrow-checker was easier, because the rules were simpler and you were forced t…

Yes, the pre-NLL version makes it clear to see why swapping the assignment lines wouldn't work.

EDIT: i think some tooling showing lifetimes for borrows would be very helpful. Can mir do this? I haven't tried it.

Re: Dave Herman’s contributions to Rust

#63
post #51
post #49

Earlier quoted context omitted.

In Rust, a function definition left-hand-side looks like an annotated pattern, e.g. foo(x : int) Therefore, one would expect to annotate the return type as, foo(x : int) : string Since the pattern is showing foo applied to x. The Rust syntax is actually confusing for both Haskell/ML programmers (where the arrow comes from) and mainstream programmers. It's too small an issue to change now though. Rust's support for pr…

That would imply that "foo(x: int)" is a string rather than a function. Haskell doesn't use that notation either, it uses -> both for the parameter list and for the return type, and separates argument names (arguably, these are poor choices, since currying is not an efficient CPU-native operation and not intuitive so distinguishing between multiple arguments and returning closures is useful, and argument names are us…

Just a nitpick, but currying is a language detail, one can potentially create an efficient implementation with or without them.

Re: Dave Herman’s contributions to Rust

#64

> A little appreciated fact: Rust was largely built by students, and many of them interned at Mozilla. So now companies make billions off of the software written in Rust and has even one student become a millionaire? Companies that appropriate such projects should start paying their fair share to people who made it possible for them to make such profits.

Being in the team that created rust would look great on any CV. I think millionaire is reachable for many of them.

Re: Dave Herman’s contributions to Rust

#65
post #63
post #51

Earlier quoted context omitted.

That would imply that "foo(x: int)" is a string rather than a function. Haskell doesn't use that notation either, it uses -> both for the parameter list and for the return type, and separates argument names (arguably, these are poor choices, since currying is not an efficient CPU-native operation and not intuitive so distinguishing between multiple arguments and returning closures is useful, and argument names are us…

Just a nitpick, but currying is a language detail, one can potentially create an efficient implementation with or without them.

Yes and of course Haskell is quite capable of supporting uncurried functions too, e.g.

foo :: (Int, Int) -> Int

foo (x, y) = ...

Re: Dave Herman’s contributions to Rust

#66
post #11

Earlier quoted context omitted.

No, not at all. I hate var & val because I never can remember which is which (from Scala, which I never really used a lot). let vs let mut is /clear/ - you can simply not mix them up.

How is it not clear that var is variable?

I'm a javascript developer.

if mutable is expensive, and should be difficult then "let mut" makes more sense.

var looks like a default to me, not a special case that needs care.

Re: Dave Herman’s contributions to Rust

#67
post #42

Rust maybe a little adhoc in places (e.g. the misappropriated Haskell/ML function syntax, enum/struct asymmetry), but overall it is a fantastic effort. It is not an easy task to combine an advanced static type-system with mainstream ergonomics, but they seemed to have pulled it off. The fact that it is also not owned and controlled by a single big tech entity is icing on the cake. I really hope it achieves even great…

Personally, I find Rust syntax to be well-designed. At least, compared to any practical programming language I know.

Quite a few times I was surprised that Rust breaks with some old patterns that were copied over and over in the last 50 years or so. For example: "match" instead of "switch", or the same if/else regardless if it is a statement or a value. These are small touches, but they show attention to detail.

Re: Dave Herman’s contributions to Rust

#68
post #49
post #45

Earlier quoted context omitted.

> misappropriated Haskell/ML function syntax, enum/struct asymmetry I'm curious, could you elaborate?

In Rust, a function definition left-hand-side looks like an annotated pattern, e.g. foo(x : int) Therefore, one would expect to annotate the return type as, foo(x : int) : string Since the pattern is showing foo applied to x. The Rust syntax is actually confusing for both Haskell/ML programmers (where the arrow comes from) and mainstream programmers. It's too small an issue to change now though. Rust's support for pr…

> one would expect to annotate the return type as

> foo(x : int) : string

> since the pattern is showing foo applied to x.

kind of like the C/C++ "declaration mirrors use" thing, i.e.

  int *foo;
which means

"the result of dereferencing `foo` is of type `int`"

which is not the same as saying

  foo : Ptr;
because in the former, you're kind of describing what `foo` is a without actually saying it, if that makes sense.

i find that way of specifying types counterintuitive in both C/C++ and MLs.

Re: Dave Herman’s contributions to Rust

#69
post #57
post #51

Earlier quoted context omitted.

That would imply that "foo(x: int)" is a string rather than a function. Haskell doesn't use that notation either, it uses -> both for the parameter list and for the return type, and separates argument names (arguably, these are poor choices, since currying is not an efficient CPU-native operation and not intuitive so distinguishing between multiple arguments and returning closures is useful, and argument names are us…

> That would imply that "foo(x: int)" is a string rather than a function But foo(x : int) is a string! It literally reads "foo applied to x". In the function definition, it appears to be used as a left-hand-side pattern which is "matched". The definition is written as if to say, whenever the term foo(x) is encountered, use this definition here. At least, that was my expectation. > Haskell doesn't use that notation ei…

> But foo(x : int) is a string!

Can you say so decisively for a language with first-class functions?

Re: Dave Herman’s contributions to Rust

#70
post #61
post #54

Earlier quoted context omitted.

Would this have worked pre-NLL?

The pre-NLL version would need some additional scopes. In some ways the current borrow-checker is a lot friendlier (there are also some things possible today that weren't before) but it was also a simpler time, where one could easily imagine the various lifetimes. Getting started with the language was harder, but I think internalizing the borrow-checker was easier, because the rules were simpler and you were forced t…

> Getting started with the language was harder, but I think internalizing the borrow-checker was easier,

So here's a funny thing: depending on what you mean, I don't think this is actually true. Let me explain.

The shortest way of explaining lexical lifetimes vs NLL is "NLL is based on a control-flow graph, lexical lifetimes are based on lexical scope." CFGs feel more complex, and the implementation certainly is. So a lot of people position this as "NLL is harder to understand."

But that assumes programmers think in the simple way. I think one of Rust's under-appreciated contributions is that programmers intuitively understand control flow graphs better than we may think, and may not intuitively understand lexical scope. Sure, by some metric, NLL may be "more complex" but practically, people only report it being easier to learn and do what they would naturally expect.

Post reply on HN