Simplify constructor function

FWIW, for me it's "add if $condition$ { to the first line of the block, add } to the end of the last line, and let rustfmt fix it.

So I write:

if can_print { match letter {
…
}}

and let rustfmt fix it up for me. I'd also note that rust-analyzer has post-fix assists (like .ifl) that could be used so that you can write a block, then add .ifc at the end and have rust-analyzer put the if condition in for you at the beginning and move the cursor to condition.

4 Likes

Sure it's definitely a tradeoff. Though i disagree that it's really more prone to goto fail than brackets. I think the punctuation solves that problem as long as you don't style your code evil, but the same could be said about brackets

if condition {
    goto fail; }
    goto fail;
if condition
    => goto fail;
    goto fail:

Yes, you could always format code confusingly, and perform a myriad of other obfuscation techniques. Rust-format should help with that. But given how your previous example was formatted I found it quite obfuscated. In fact so is your most recent example with => as well in my opinion.

I prefer explicitness and clarity over saving a few characters, and I like that Rust leans in that direction. Like @farnz wrote it is also easy to write and let rustfmt fix it.

I'm not sure where people who want to save a few characters are coming from. Certainly not from the same direction as I am (embedded hard real time human safety critical systems). Clarity and correctness is trumps saving 5 keystrokes every time.

The only way I could see a bracketless construct working well would be in a language like Python or Haskell, where you have consistent meaningful indentation. Here the code is visually clear when you read it. It is arguably a better solution than curly brackets since you can't make the indentation mismatch with the semantics. (And no, it is never going to happen in Rust, waaay to late for that.)

3 Likes

It's about making code easier to change from one state to another and prototype ideas, not so much about a superfluous visual difference. Adding and removing changes happens constantly even if you know what you're doing, and it's nice to reduce the friction of iterative development.

But like I said it might not gel with Rust as a language - to me the downsides are:

  • It introduces a choice when coding that doesn't have an obvious answer most of the time, so people have to develop a rule of thumb at least subconsciously.

  • => provides less visual separation between instructions than bracketing, line breaking, & indentation. This can make individual lines more complex, even if it takes up less visual space overall. This is probably what most people would base their rule of thumb on.

  • It probably shouldn't allow chained constructs like if/else, try/catch. Even with consistent behavior it would be easy to confuse.

Also an advantage I just want to point out cause it's cool; it allows method-style chaining, so you get let-chains automatically (among other possible syntax):

if let Some(a) = a_option
    => if let Some(b) = b_option
    => if let Some(c) = c_option
    => if c > 0
    => for d_option in d_options
    => if let Some(d) = d_option
{
    println!("{:?}", (a, b, c, d));
}

If anything I find this much easier to both read and modify than the alternative since the instructions are laid out linearly, but maybe others would disagree.

Honestly it's tempting to make a file-wide macro attribute cause that feels like the best of both worlds, at least to play around with. Enabled during development, disabled when the project is in a stable state.

1 Like

You had me interested until you threw in the for loop in the middle there. If it was just if let / if I could definitely see that one working. But the loop doesn't stand out enough for me there. I want to see loops and algorithm complexity very clearly, and there the for loop just merged visually with the rest of the operations.

(Keep in mind that I'm talking with my real-time low latency hat on here.)

4 Likes

From my perspective, it's already simple to change code from one state to another - select the block I want to make conditional, type { (which causes my editor to put { and } around the selected block) and add the conditional. Then hit "save", and let rustfmt fix my formatting.

Your proposal doesn't save me much in time, but does add readability issues; for example, your chained version has a for hidden in it that I did not see until @Vorpal pointed it out; this is, in part, since Rust uses blocks to indicate nesting, while you've got what I assume is nesting hidden by the fat arrow operator. I like the rightward drift that Rust is prone to for the same reasons I like it in Python: it makes it obvious when I've got deep nesting, which in turn implies it's time to refactor to reduce the nesting.

3 Likes

I think it is not important. You should be simplify the code using the following methods:

fn new() -> Self {
    Self {
        member1: 3,
        member2: "Feature Request",
    }
}

1 Like

semantic whitespace would mix horribly with macros unless you implemented it as a desugaring pass that happened before macro expansion.

1 Like

Thanks everyone for answering. it seems like that change is something the general rust community doesnt really care about, so that kinda answers my questions

1 Like