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…
Weird Expressions in Rust
101–110 of 155 posts
Re: Weird Expressions in Rust
#102Rust 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?
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
#103Earlier 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…
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
#104Re: Weird Expressions in Rust
#105This 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!"
Re: Weird Expressions in Rust
#106Earlier 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…
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
#107Earlier 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
Re: Weird Expressions in Rust
#108Does 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-...
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
#109they 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.
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
#110Earlier 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.
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.