Live data from Hacker News

Weird Expressions in Rust

wakunguma.com

31–40 of 155 posts

Re: Weird Expressions in Rust

#31
post #25

Earlier quoted context omitted.

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.

> If a language that claims to be security focused Rust does not claim to be particularly security-focused, only memory safe. Also, this means that you'd consider any expression-based language to be inherently a security problem.

"Memory safety" is an aspect of computer security. And security is the first listed value in rust's mission statement.

Rust is not written as a pure expression based language. And as we all know very well from the experience with C and JS, any unexpected and weird looking code has the potential to hide great harm. Allowing programmers to stray too much from expected idioms is dangerous.

Re: Weird Expressions in Rust

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

That sounds superficially reasonable to me and I'm all for regularity in programming language semantics but on thinking about it further, I actually think it's a design flaw.

It makes no more sense to me for "return " to have a type than it does to make "if " or "break" or "{" or any other keyword to have a type. These are syntactic elements.

Rust's type system is clearly inspired by Hindley-Milner and most languages using such a type system either don't even have a return keyword.

Even if you disagree with this argument, this design decision has resulted in all these weird/confusing but absolutely useless code examples and there is no upside that I can see to this decision in terms of language ergonomics. What practical value is it to users to allow "return " to itself be an expression? That you can use such an "expression" as arguments to function calls with hilarious wtf consequences? It's a piece of syntactic sugar.

Re: Weird Expressions in Rust

#33
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.

Re: Weird Expressions in Rust

#34
post #31

Earlier quoted context omitted.

> If a language that claims to be security focused Rust does not claim to be particularly security-focused, only memory safe. Also, this means that you'd consider any expression-based language to be inherently a security problem.

"Memory safety" is an aspect of computer security. And security is the first listed value in rust's mission statement. Rust is not written as a pure expression based language. And as we all know very well from the experience with C and JS, any unexpected and weird looking code has the potential to hide great harm. Allowing programmers to stray too much from expected idioms is dangerous.

It is an aspect, but it Rust does not promise your core is secure.

It’s not purely expression based but it is very close to it, there’s only a few kinds of statements, the vast majority of things are expressions.

Re: Weird Expressions in Rust

#35

Earlier quoted context omitted.

I wonder, what's the "weirdest" expression in Go? Here's one: type Foo struct{} func (Foo) Bar() { println("weird...") } func main() { ([...]func(){^^len(` `): (&Foo{}).Bar})[cap(append([]any(nil),1,2,3))]() }

Makes sense to me, [...]func() is an array of functions, and [...]T{index: value} is uncommon but still perfectly comprehensible

That's why I like Rust /s

Re: Weird Expressions in Rust

#36
post #32
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…

That sounds superficially reasonable to me and I'm all for regularity in programming language semantics but on thinking about it further, I actually think it's a design flaw. It makes no more sense to me for "return " to have a type than it does to make "if " or "break" or "{" or any other keyword to have a type. These are syntactic elements. Rust's type system is clearly inspired by Hindley-Milner and most languages…

Respectfully, "it makes no sense to me" isn't an argument. if and break both have types in Rust as well.

> don't even have a return keyword.

This is because they are not procedural languages, it has nothing to do with the type system.

> there is no upside that I can see to this decision in terms of language ergonomics.

There's tremendous upside! That's why lots of languages choose this. For example, there is no need for the ternary in Rust: if can just do that.

> What practical value is it to users to allow "return " to itself be an expression?

Code like this just works:

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => return,
        };
That is, if return wasn't an expression, we'd have a type error: the two arms would have incompatible types.

Re: Weird Expressions in Rust

#37
post #32
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…

That sounds superficially reasonable to me and I'm all for regularity in programming language semantics but on thinking about it further, I actually think it's a design flaw. It makes no more sense to me for "return " to have a type than it does to make "if " or "break" or "{" or any other keyword to have a type. These are syntactic elements. Rust's type system is clearly inspired by Hindley-Milner and most languages…

In practice, it's quite a useful feature, because you can write things like this:

    let day_number = match name {
        "Sunday" => 0,
        "Monday" => 1,
        "Tuesday" => 2,
        "Wednesday" => 3,
        "Thursday" => 4,
        "Friday" => 5,
        "Saturday" => 6,
        _ => return Err("invalid day")
    };

Re: Weird Expressions in Rust

#38
post #32
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…

That sounds superficially reasonable to me and I'm all for regularity in programming language semantics but on thinking about it further, I actually think it's a design flaw. It makes no more sense to me for "return " to have a type than it does to make "if " or "break" or "{" or any other keyword to have a type. These are syntactic elements. Rust's type system is clearly inspired by Hindley-Milner and most languages…

The issue with `return expr` not having a type is that you lose the ability to write something like

let y = match option { Some(x) => x, None => return Err("whoops!"), };

Without a type, the None branch loses the ability to unify with the Some branch. Now you could say that Rust should just only require branches’ types to unify when all of them have a type, but the ! never type accomplishes that goal just fine.

Re: Weird Expressions in Rust

#40
post #32
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…

That sounds superficially reasonable to me and I'm all for regularity in programming language semantics but on thinking about it further, I actually think it's a design flaw. It makes no more sense to me for "return " to have a type than it does to make "if " or "break" or "{" or any other keyword to have a type. These are syntactic elements. Rust's type system is clearly inspired by Hindley-Milner and most languages…

We can use match to do pattern matching:

  let name = match color_code {
    0 => "red",
    1 => "blue",
    2 => "green",
    _ => "unknown",
  };
The RHS of the `=>` has to be an expression, since we're assigning it to a variable. Here, you should already see one "useful" side-effect of what you're calling "syntactic elements" (I'd perhaps call them "block statements", which I think is closer to the spirit of what you're saying.) The whole `match … {}` in the example above here is an expression (we assign the evaluation of it to a variable).

> What practical value is it to users to allow "return " to itself be an expression?

Now, what if I need to return an error?

  let name = match color_code {
    0 => "red",
    1 => "blue",
    2 => "green",
    _ => return Err("unknown color"),
  };
The expression arms need to be the same type (or what is the type of `name`?). So now the type of the last branch is !. (Which as you hopefully learned from TFA, coerces to any type, here, to &str.)

There's more ways this "block statements are actually expressions" is useful. The need not be a ternary operator / keyword (like C, C++, Python, JS, etc.):

  let x = if cond { a } else { b };
In fact, if you're familiar with JavaScript, there I want this pattern, but it is not to be had:

  const x;  // but x's value will depend on a computation:
  // This is illegal.
  if(foo) {
    x = 3;
  } else {
    x = 4;
  }
  // It's doable, but ugly:
  const x = (function() { if(foo) { return 3; } else { return 4; }})();
  // (Yes, you can do this example with a ternary.
  // Imagine the if branches are a bit more complicated than a ternary,
  // e.g., like 2 statements.)
  
Similarly, loops can return a value, and that's a useful pattern sometimes:

  let x = loop {
    // e.g., find a value in a datastructure. Compute something. Etc.
    if all_done {
      break result;
    }
  };
And blocks:

  let x = {
    // compute x; intermediate variables are properly scoped
    // & cleaned up at block close.
    //
    // There's also a slight visual benefit of "here we compute x" is
    // pretty clearly denoted.
  };
> Even if you disagree with this argument, this design decision has resulted in all these weird/confusing but absolutely useless code examples

I think one can cook up weird code examples in any language.

Post reply on HN