Live data from Hacker News

Weird Expressions in Rust

wakunguma.com

91–100 of 155 posts

Re: Weird Expressions in Rust

#91
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…

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

#92

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

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…

We've been going down this road for a long time now. E.g. "throw" is a (void-typed) expression in C++ already for similar reasons, although it doesn't go far enough without a proper bottom type. C# took it further and added the type so that you can write things like e.g. `x = y ?? throw new Error(...)`. There's no obvious reason why "return" should be conceptually different.

A better question at this point, arguably, is why there should even be an expression/statement distinction in the first place. All imperative statements can be reasonably and sensibly represented as expressions that produce either () or "never". Semicolon then is just a sequencing operator, like comma in C++.

Re: Weird Expressions in Rust

#93
post #85

Earlier quoted context omitted.

> "return " is not just an expression which can be typed. Yes, it is, and it can. It has the type !, no matter the type of .

It only has type !, if the return type of the lexically enclosing function declaration has the same type as that of , otherwise it's illformed. For any expression NOT involving "return", I can write, for example: const Z = but I cannot if contains a return embedded somewhere. The existence of a "return" somewhere in an expression changes the character of the entire expression. I.e. there are two classes of "expressio…

Okay, I think we are indeed talking past each other and I see what you are saying here. I am not sure that I agree, exactly, but I appreciate your point. I'm going to have to think about it a bit more.

Re: Weird Expressions in Rust

#95

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!"

Re: Weird Expressions in Rust

#97

I don't understand the one with dont(). Why does i.get() end up false at the end? Shouldn't it be true after having been set by dont()?

The final line "assert!(i.get());" asserts that i.get() is true in the end. The ! character here belongs to the assert! macro, not a boolean negation. (This unfortunately gets a bit weird-looking when you want to write sensible stuff like "if !matches!(x, Some(5..=10)) { ... }".)

Oops, I see, thanks!

Re: Weird Expressions in Rust

#98
post #85

Earlier quoted context omitted.

> "return " is not just an expression which can be typed. Yes, it is, and it can. It has the type !, no matter the type of .

It only has type !, if the return type of the lexically enclosing function declaration has the same type as that of , otherwise it's illformed. For any expression NOT involving "return", I can write, for example: const Z = but I cannot if contains a return embedded somewhere. The existence of a "return" somewhere in an expression changes the character of the entire expression. I.e. there are two classes of "expressio…

You can write it just fine if `const Z` is itself nested inside a function definition.

And this isn't really any different from variable references, if you think about it. If you have an expression (x + 1), you can only use it somewhere where there's an `x` in scope. Similarly, you can only use `return` somewhere where there's a function to return from in scope. Indeed, you could even make this explicit when designing the language! A function definition already introduces implicit let-definitions for all arguments in the body. Imagine if we redefined it such that it also introduces "return" as a local, i.e. given:

   fn foo(x: i32, y: i32) -> i32 {
     ...
   }
the body of the function is written as if it had these lines prepended:

   let x = ...;
   let y = ...;
   let return = ...;
   ...
where "return" is a function that does the same thing as the statement. And similarly for break/continue and loops.

The thing that actually makes these different from real variables is that they cannot be passed around as first-class values (e.g. having the function pass its "return" to another function that it calls). Although this could in fact be done, and with Rust lifetime annotations it would even be statically verifiable.

Re: Weird Expressions in Rust

#99
post #25
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…

If a language that claims to be security focused is easily able to express constructs that human minds find barely comprehensible, or worse, then this is itself arguably a security issue: it's impossible to check the correctness of logic that is incomprehensible.

"never" is an easily comprehensible concept once you start asking the right questions.

But also, all examples in TFA are very artificial convoluted code. Meaning that you can write things like these just like you can write something like &&&...x - but why would you? Actual real-world uses of this feature are all quite readable.

Re: Weird Expressions in Rust

#100
post #54
post #43

Earlier quoted context omitted.

What's the threat model? If you're reviewing untrusted or security-critical code and it's incomprehensible, for any reason, then it's a reject. Syntax alone can't stop sufficiently determined fools. Lisp has famously simple syntax, but can easily be written in an incomprehensible way. Assembly languages have very restrictive syntax, but that doesn't make them easy to comprehend. Rust already has a pretty strong type…

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# keeps adding clever syntax sugar, while Go officially gave up on removing its noisiest boilerplate.

D has fun stuff like UFCS, template metaprogramming, string mixins, lambdas — enough to create "incomprehensible" code if you wanted to.

You're talking about modern languages vs relics of the past, but all the languages you mention are older than Rust.

Post reply on HN