News for hackers. Stuff that matters.
Re:Rust for JavaScript Developers – Functions and Control Flow by hardwaregeek on Sunday July 05, 2020 @08:31PM (#23743530)
It'd be nice to mention that Rust has if expressions, not if statements.

Therefore the example could be simplified to:

   fn calculate_tax(income: i32) -> i32 {
     if income < 10 {
       0
     } else if income >= 10 && income < 50 {
       20
     } else {
       50
     }
   }
Re:Rust for JavaScript Developers – Functions and Control Flow by eximius on Monday July 06, 2020 @02:48AM (#23745334)
Rust can also match on ranges which is perhaps the most idiomatic form for this.
Re:Rust for JavaScript Developers – Functions and Control Flow by delta1 on Monday July 06, 2020 @08:51AM (#23747326)

    fn calculate_tax(income: i32) -> i32 {
        match income {
            0..=9 => 0,
            10..=49 => 20,
            _ => 50,
        }
    }
https://play.rust-lang.org/?version=stable&mode=debug&editio...
Re:Rust for JavaScript Developers – Functions and Control Flow by nyanpasu64 on Monday July 06, 2020 @02:53PM (#23751366)
This behaves differently for negative incomes, which are not prohibited by the i32 argument passed in (u32 cannot take on negative values).
Re:Rust for JavaScript Developers – Functions and Control Flow by delta1 on Tuesday July 07, 2020 @04:09AM (#23756827)
Yeah I was just literally translating the previous code as an example, I didn't get the business rules specification

¯\_(ツ)_/¯

Re:Rust for JavaScript Developers – Functions and Control Flow by eximius on Monday July 06, 2020 @08:28PM (#23754351)
Ranges support negatives, so thats nice. Though i32::MIN..=9 is at least slightly odd.
Re:Rust for JavaScript Developers – Functions and Control Flow by 65536 on Sunday July 05, 2020 @11:28PM (#23744416)
Speaking of which, coming from Rust (well, when I say it like that it sounds like Rust is the only language I ever used which is of course not true. I think Rust as a first language would be highly unusual still), I enjoyed being able to say

Rust code:

    let foo = if x <= 0
    {
        0
    }
    else if something_else > 50
    {
        9000
    }
    else
    {
        42
    };
And I miss this in Swift.

The ternary operator is fine on its own but I’m not a huge fan of nested ternary operators. With a bit of whitespace it's somewhat readable still but still not as comfortable and easy to read correctly.

Swift code:

    let foo = x <= 0 ?                0 :
             (somethingElse > 50 ? 9000 :
                                     42 )
One way of writing something that is more similar to the way I'd write it in Rust would be to make a closure and then run it.

Swift code:

    let foo =
    { () -> Int in
        if x <= 0
        {
            return 0
        }
        else if somethingElse > 50
        {
            return 9000
        }
        else
        {
            return 42
        }
    }()
But it's a bit annoying still, both to read and to write. Also, even in the current version of Swift (Swift 5), the compiler cannot infer the return type of the closure on its own even though all of the branches return an Int, so I'd have to explicitly annotate that as I have done in the code above.

I guess for a lot of people they would just make foo mutable and write the code as

Swift code:

    var foo = 42
    
    if x <= 0
    {
        foo = 0
    }
    else if somethingElse > 50
    {
        foo = 9000
    }
I concede that this is probably the most readable out of all of the three Swift code samples in my comment. But the point is that I didn't want foo to be mutable. I wanted to assign a value to it based on some simple logic and have it be immutable.
Re:Rust for JavaScript Developers – Functions and Control Flow by bobbylarrybobby on Monday July 06, 2020 @12:45AM (#23744771)
I find ternary operators perfectly readable if you split the parts across lines — they map exactly to the conditions and statements in an if-else group.

    Cond1 // if this
    ? Result1 // return this
    : cond2 // else if this
    ? Result2 // return this
    : cond3 // else if this
    ? Result3 // return this
    : ResultElse // else return this
Re:Rust for JavaScript Developers – Functions and Control Flow by mekkkkkk on Monday July 06, 2020 @06:13AM (#23746297)
I've come to hesistently accept nested ternaries, but I try to have all lines lead with a colon. This kinda mimics a switch statement with returns.

  firstPossible ? thenThis
    : secondPossible ? thenThisOtherThing
    : thirdPossible ? thenThisThirdThing
    : defaultThing
Always fun to see how people treat ternary nesting. They still feel a bit naughty to me. The terseness is sort of unbeatable though.
Re:Rust for JavaScript Developers – Functions and Control Flow by Kkoala on Monday July 06, 2020 @08:48AM (#23747296)
It's funny how people have so many different preferences for ternary formatting. I can't think of any other operator that would have tens of different format prefs.
Re:Rust for JavaScript Developers – Functions and Control Flow by pests on Monday July 06, 2020 @02:11AM (#23745165)
Which is not true in PHP up until the most recent version (iirc) due to it being left associative instead of right associative you are assuming.
Re:Rust for JavaScript Developers – Functions and Control Flow by amenod on Monday July 06, 2020 @02:11AM (#23745167)
True, or even:

    Cond1 // if this
      ? Result1 // return this
      : cond2 // else if this
        ? Result2 // return this
        : cond3 // else if this
          ? Result3 // return this
          : ResultElse // else return this
Re:Rust for JavaScript Developers – Functions and Control Flow by giantDinosaur on Monday July 06, 2020 @05:02AM (#23745964)
Goodness me that has potential to become something truly hideous.
Re:Rust for JavaScript Developers – Functions and Control Flow by amenod on Monday July 06, 2020 @01:11PM (#23749998)
It's actually not that bad in practice... But I guess the pragmatic formatting is "whatever `prettier` does by default" anyway. :)
Re:Rust for JavaScript Developers – Functions and Control Flow by Kkoala on Monday July 06, 2020 @08:46AM (#23747285)
It's funny how people have so many different preferences for ternary formatting. I can't think of any other operator that would have tens of different format prefs.
Re:Rust for JavaScript Developers – Functions and Control Flow by skocznymroczny on Monday July 06, 2020 @02:48AM (#23745336)
I dislike the ternary operator in languages like C++. And many languages copy-paste it because they are used to it. I much prefer the more literal and reversed form in Python.

Instead of:

int salary = isEmployed() ? 2000 : 0

I prefer:

int salary = 2000 if isEmployed() else 0

Re:Rust for JavaScript Developers – Functions and Control Flow by JimDabell on Monday July 06, 2020 @04:13AM (#23745731)
Yes, it also makes the larger example somewhat readable:

    func calculate_tax(income):
        return 0 if income < 10 else 20 if income < 50 else 50
Re:Rust for JavaScript Developers – Functions and Control Flow by jfkebwjsbx on Monday July 06, 2020 @09:11AM (#23747487)
I love that idea, but I still prefer it’d read the same as an if. Meaning the condition first and the false case last.
Re:Rust for JavaScript Developers – Functions and Control Flow by nicoburns on Monday July 06, 2020 @10:04AM (#23747942)
Rust implements this:

    let foo = if is_employed() { 2000 } else { 0 }
Re:Rust for JavaScript Developers – Functions and Control Flow by w-ll on Sunday July 05, 2020 @11:34PM (#23744450)
I'd guess i fall into the mutable camp, while sometimes doing a closure.

Nested ternary if statements scare me from my PHP days, and noticed inlined closures can at times be harder to grok at a glance.

Re:Rust for JavaScript Developers – Functions and Control Flow by hardwaregeek on Monday July 06, 2020 @01:09AM (#23744901)
Agreed. Plus if the else clause has a side effect, you can't assign it to the variable, which means you need to instantiate to null or a dummy value. Very messy.

What's funny is that expression oriented languages translate really nicely to stack VMs. My hobby language compiles down to WASM and it was almost trivial to code gen if expressions.

Re:Rust for JavaScript Developers – Functions and Control Flow by jurip on Monday July 06, 2020 @03:46AM (#23745614)
Agreed about missing if and switch expressions in Swift. My preferred way of writing that would be:

    let foo: Int
    if x <= 0 {
        foo = 0
    } else if somethingElse > 50 {
        foo = 9000
    } else {
        foo = 42
    }
That way you get immutable foo and the compiler will shout at you if you forget to assign the value in one branch. It's not quite as nice as an expression, but it's less punctuation than the closure and the result is just as safe.
Re:Rust for JavaScript Developers – Functions and Control Flow by GrayShade on Monday July 06, 2020 @10:25AM (#23748218)
It's probably not the most idiomatic thing, but in Rust you can write:

    let foo = match () {
        _ if x <= 0 => 0,
        _ if something_else > 50 => 9000,
        _ => 42,
    };
Re:Rust for JavaScript Developers – Functions and Control Flow by yen223 on Sunday July 05, 2020 @08:37PM (#23743564)
Also worth pointing out that if expressions is the Rust alternative to Javascript's ternary operator
Re:Rust for JavaScript Developers – Functions and Control Flow by bryanrasmussen on Monday July 06, 2020 @01:38AM (#23745031)
I don't know Rust - but is it possible to write it like this?

fn calculate_tax(income: i32) -> i32 { if income < 10 { 0 } if income < 50 { 20 } 50 }

on edit: tried to fix formatting but didn't work.

Re:Rust for JavaScript Developers – Functions and Control Flow by TheDong on Monday July 06, 2020 @02:50AM (#23745347)
If you wanted to list out cases without having to use `if`, `else if`, you'd idiomatically use match:

    fn calculate_tax(income: i32) -> i32 {
        match income {
            0..10 => 0,
            10..50 => 20,
            _ => 50,
        }
    }
See this playground for a couple other alternatives using match too https://play.rust-lang.org/?version=nightly&mode=debug&editi...

As others explained, you do need a default case (either an 'else' in your if statement, or an exhaustive match), otherwise how would the expression typecheck?

For a concrete example, if you use an 'if' only, you can have the following:

    let x = if income < 10 { 0 };
At that point, there's no way to statically know x's type. If income is >= 10, x is what?

In order to convince the compiler x has a statically knowable type, the "if" expression need an else statement, or should be converted into a match that the compiler can prove is exhaustive.

Re:Rust for JavaScript Developers – Functions and Control Flow by bad-apple on Monday July 06, 2020 @03:29AM (#23745538)
Nitpick: I'm pretty sure that "11..50" should be a "10..50".
Re:Rust for JavaScript Developers – Functions and Control Flow by TheDong on Monday July 06, 2020 @03:38AM (#23745584)
Edited, yeah. Off-by-one errors, can't live without em.
Re:Rust for JavaScript Developers – Functions and Control Flow by bad-apple on Monday July 06, 2020 @04:04AM (#23745695)
If you'd used 50.. instead of _, Rust would've caught this error for you. ;)

https://play.rust-lang.org/?version=nightly&mode=release&edi...

Re:Rust for JavaScript Developers – Functions and Control Flow by bryanrasmussen on Monday July 06, 2020 @05:04AM (#23745975)
Thanks!
Re:Rust for JavaScript Developers – Functions and Control Flow by conradludgate on Monday July 06, 2020 @02:25AM (#23745221)
It wouldn't work like that but if you made them else if and else branches respectively then yes it would. Each if/if else/else block as a whole is a single statement. But two if statements and a literal is three individual statements
Re:Rust for JavaScript Developers – Functions and Control Flow by vpzom on Monday July 06, 2020 @01:39AM (#23745037)
No, if expressions can basically only be used with else, otherwise you have a type mismatch
Re:Rust for JavaScript Developers – Functions and Control Flow by rkwz on Sunday July 05, 2020 @09:16PM (#23743759)
Thanks for reading! Will mention this in future chapters :)