Hacker News new | ask | show | jobs
by alfiedotwtf 3400 days ago
From moving from Perl to Rust, the only thing that I miss is the postfix "if":

  return true if number > 2;
VS:

  if number > 2 {
    return true
  }
I find that one-liners like these are really ergonomic.
4 comments

You can do something similiar in rust. 'if' is an expression, so it can appear on the right hand side of an assignment.

  let x = if number > 2 { "yes" } else { "no" };
It's not quite the same, and I'm not sure what the failure case would be if the 'else' statement was ommitted, but it comes close.

After experimenting with Rust and Elixir I've really come to like the 'everything is an expression' approach. That and pattern matching can make some things really expressive.

Ah yes... ternaries. Actually, it's two things I miss :)
That would this in rust: if number { true } else { false }

If it's the last expression it will implicitly return the values. Easily fits on one line.

My one puny objection to this is that rustfmt won't put the arms on a single line, but will always break and indent around the blocks. That makes Rust's expression-if considerably more verbose than what Perl has, or even the ternary operator.
Hm. I wonder if this is configurable, or if there's an RFC open for this.
I have found using conditionals as expressions super useful, like:

``` fn foo(number: u32) -> bool { if number > 2 { true } else { false } } ```

I mean obviously in this situation you could just have the body of the function be `number > 2` but I write a lot of Rust code that does similar things now.

In Perl, it's fairly idiomatic to use a postfix condition on a return like that when doing early return. Some of that is obviated by Rust being typed, some is not. e.g.

    sub compute_interest( $amount, $interest ) {
        return $amount if $interest == 0; # Quick return
        die "We don't allow computation of negative interest rates" if $interest < 0; # Throw an exception
    
        # Do the actual work
        ...
    }
Edit: Also, it's worth noting that Perl enforces some behavior on this by only allowing postfix conditionals to follow a single statement, not blocks, so it's not just a regular conditional with the order reversed.
I've always disliked this aspect of Perl... I prefer control flow to be obvious.
Hiding the actual control part on the right is pretty bad, yes.

Other than that, early returns can simplify flow a lot - otherwise you may have to do massive nesting ifs or many flags. Or even goto or exceptions.

It's less bad than it seems, since it's a common idiom in Perl, so you're used to looking at it. It can be quite bad if abused, but so can so much in Perl.

When used with a return or die (or my personal favorite for debugging with 'warn "FOO" if $ENV{DEBUG};"), the fact that flow is affected is obvious by the very first characters in the statement, so it's obvious to then look for when it applies.

Like so many features of languages, how it looks from the outside compared to how it looks from those that are well versed in the language can be quite different (not to say that everything that looks like a wart in Perl is okay once you get used to it, every language has real warts). That's another aspect to this whole thing, how much to you emphasize ergonomics that are primarily for learning and novices. Features focused at novices to the expense of those familiar with the language are interesting, because they may draw a lot of people to your language, but you may not retain them very well.

yep, that works... but having it postfix affords salience
ProTip:

In both languages you can do the following:

    return number > 2;
Not really the same thing. The Perl version is generally used as an early abort either from a subroutine or a loop.

    return if($number > 2);
Is equivalent to:

    if($number > 2){
        return;
    }
I didn't know that. Thanks for explaining it.
But that's different. Perl's variant isn't that intuitive.
Also that was just an example. Another along the same line:

  x = 42 if y > 7;
Rather than

  x = match y > 7 { true => 42, false => 0 };
Or even:

  foo() if bar();
Rather than:

  if bar() { foo() }
Given how crucially important scopes are to Rust, this would be a uniquely poor fit. :P
Yeah, I totally understand why not. Just my comments from the peanut gallery :)