Live data from Hacker News

Weird Expressions in Rust

wakunguma.com

101–110 of 155 posts

Re: Weird Expressions in Rust

#101

Earlier quoted context omitted.

return is an expression in Rust, and it fits in well. There are very few statements: https://doc.rust-lang.org/stable/reference/statements.html and a lot of expressions: https://doc.rust-lang.org/stable/reference/expressions.html

We're speaking past each other since there's "expression" as defined in the Rust specification vs "expression" as in ordinary computer science, and Rust's use of return is certainly not an expression in the latter sense. It is shoehorned into being called an expression but it has no semantically meaningful type, it is an effect. A type is (carefully but somewhat arbitrarily) assigned to it, which is why some of those…

Return (or other effects) does make sense as an expression in a functional language. Typically, OCaml has `raise Exception` which is also an expression, with the same type as `return` or any never returning function. And exceptions can also be used to implement a user-defined `return` function.

Re: Weird Expressions in Rust

#102
post #74

Rust noob here. That '!' type seemed weird in the first few examples but starts to make sense later on. It's essentially a "pseudo type" for everything that is syntactically an expression, but will never return anything, because evaluating it causes the entire statement to be canceled. Is that correct?

Not necessarily the entire statement, just some outer expression.

Which might make more sense when you remember that the only statements in Rust are various declarations (`let`, `type`, `fn` etc) and macro invocations. Everything else is an "expression statement", including blocks and loops. Thus you can do stuff like:

    // Compute the first Fibbonaci number >10
    let n = {
        let mut x1 = 0;
        let mut x2 = 1;
        loop {
            let x = x1 + x2;
            if x > 10 { break x }
            x1 = x2;
            x2 = x;
        }
    };
Note that `break` never leaves the let-statement here - it just terminates the loop expression and forces it to yield a value (`break` without arguments yields (), and ditto for loops without break).

You can also break out of regular blocks if they are labelled and you use the labelled form of break:

   let x = 'label: { ... break 'label 42 ... }
This all can very easily lead to convoluted code if not used sparingly, but sometimes a mutating loop with mutable data encapsulated within and a break to yield it once the computation is complete is genuinely the most straightforward way to write something.

Re: Weird Expressions in Rust

#103

Earlier quoted context omitted.

Steve, I know you're an authority on the language but you've dismissed the point being made here without engaging with it. Return is a statement in the minds of most programmers, but an expression in the language. That was a very pragmatic decision that required an unintuitive implementation. As a result, we've got this post full of code that is valid to the compiler but doesn't make a lick of sense to most programme…

> Return is a statement in the minds of most programmers I would take issue with this, sure, for a lot of people, they may be bringing assumptions over from languages where assignment is a statement. That doesn't make them correct. > required an unintuitive implementation To some people, sure. To others, it is not unintuitive. It's very regular, and people who get used to "everything is an expression" languages tend…

> people who get used to "everything is an expression" languages tend to prefer it, I've found

I.e., if we bias our sample to the data points proving our point then our point is proven. It's like that quip about how every car insurance company can simultaneously claim "people who switched saved hundreds of dollars in average."

I also like "everything is an expression" languages, but I don't think that's a fantastic argument.

Re: Weird Expressions in Rust

#105

This post is missing my favorite one! fn evil_lincoln() { let _evil = println!("lincoln"); } What's weird about this? To understand what evil_lincoln is doing, you have to understand very old Rust. Here's the commit that introduced it: https://github.com/rust-lang/rust/commit/664b0ad3fcead4fe4d2... fn evil_lincoln() { let evil log was a keyword to print stuff to the screen. Hence the joke, https://en.wikipedia.org/wi…

A dog entered a tavern and said: "I cannot see anything, I'll open this one!"

Tough crowd.

Re: Weird Expressions in Rust

#106
post #100
post #54

Earlier quoted context omitted.

Many modern language designers focus on shaping expressibility rather than providing the maximum possible flexibility because their designers learned from C, Lisp and other languages that made mistakes. Examples lamguages are Java, C#, D, Go... some arguably with more success than others. But language design that gave ultimate expressive power to the the programmer is a relic of the past.

??? "Expressibility" and "expressive power" are vague and subjective, so it's not clear what you mean. I suppose you object to orthogonality in the syntax? Golang and Java definitely lack it. But you also mention C in the context of "maximum possible flexibility"? There's barely any in there. I can only agree it has mistakes for others to learn from. There's hardly any commonality between the languages you list. C# k…

Have you ever seen submissions to IOCCC or Underhanded C Code Contest? That is what too much syntactic flexibility looks like (if taken to the extreme).

If you want your code to be secure, you need it to be correct. And in order for it to be correct, it needs to be comprehensible first. And that requires syntax and semantics devoid of weird surprises.

Re: Weird Expressions in Rust

#107

Earlier quoted context omitted.

Hmm my read is this is a slight overstatement - Rust was always built with the idea of expressions as first class citizens, but practicality and performance requires expression-breaking keywords like “return” which don’t fit neatly in an ML-ish language and have a few plain old hacks associated with implementing them (not “hack” as in lacking robustness; I mean theoretically/formally inelegant). Likewise there’s some…

Haskell has `bottom`[1] (see also [2]), which acts like Rust's `return` from a type checking perspective. I wouldn't call using a uninhabited type for the type of a return expression theoretically inelegant. On the contrary, I find it quite pleasing. [1]: https://wiki.haskell.org/Bottom [2]: https://en.wikipedia.org/wiki/Bottom_type

On the more mainstream side of things, Typescript also has a bottom type called `never` which is used to type unreachable/exceptional code.

Re: Weird Expressions in Rust

#108

Does anyone know why `union` isn't a reserved word in Rust? Most contextual keywords in other languages come from either: 1. Features that were added after the language was in wide use and can't add keywords without breaking existing code. 2. Features where the word is particularly useful elsewhere, so would be painful to reserve (like `get` and `set` in Dart). But neither of those seem to apply to Rust. As far as I…

It's simply that Rust has higher standards for breaking changes than "probably not in wide use." In other words, that someone could have had `let union =`... somewhere was a reason to make it contextual. https://rust-lang.github.io/rfcs/1444-union.html#contextual-...

Ooooooh, I see my confusion now.

My brain switched off and I got enums and unions confused. I was like, wait, hasn't Rust had them since day one? I was thinking of `enum`, not `union`. My bad.

Re: Weird Expressions in Rust

#109
post #5

they exist because whole language built to treat expressions as firstclass citizens : blocks, ifs, matches, even macros as expressions that return values. so once you internalize that, all these weirdo one liners are artifacts. just artifact of a system where expressions compose infinitely. the syntax tree runs deeper than most people's habbits allow. you hit that depth and brain says this is wrong but compiler's all…

its not just that some things you would usually think are control flow are expressions, its also that there are unusual rules around coercing the `noreturn` type.

The only "unusual" rule here is that Rust offers the zero type addition, but does not provide the (much more complicated) other type additions

So Rust does have: String + ! = String

But Rust doesn't have: String + i32 = Either

Note that the never type ! isn't special here, Rust will also cheerfully: String + Infallible = String or if you were to define your own empty type like so:

    enum MyEmptyType {} // MyEmptyType has no possible values
Now under type arithmetic String + MyEmptyType = String and indeed that works in Rust.

Edited: Syntax fix

Re: Weird Expressions in Rust

#110

Earlier quoted context omitted.

We're speaking past each other since there's "expression" as defined in the Rust specification vs "expression" as in ordinary computer science, and Rust's use of return is certainly not an expression in the latter sense. It is shoehorned into being called an expression but it has no semantically meaningful type, it is an effect. A type is (carefully but somewhat arbitrarily) assigned to it, which is why some of those…

I do think we're speaking past each other. I don't fully agree with your "CS sense of the term," as Rust does have a semantically meaningful type: !. This is all pretty bog-standard stuff. Rust isn't doing anything weird or novel here.

I do wonder how many languages have the "never returns" type explicitly available. Typescript and Rust.... Haskell has bottom but I wonder semantically how much space there is between bottom and "never return". Obviously laziness makes things weird.

This is what I find interesting in this generation of languages though. Any C programmer understands the notion of an infinite loop, and the value of conditional expressions like ternary ops. But now languages are realizing that when you start treating more and more things as expressions, you really want to start giving names to things that you wouldn't name in the past.

Post reply on HN