7 ms·
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
by hardwaregeek 6y ago
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
}
}
- yen223 6y agoAlso worth pointing out that if expressions is the Rust alternative to Javascript's ternary operator
- rkwz 6y agoThanks for reading! Will mention this in future chapters :)
- 65536 6y agoSpeaking 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.
- w-ll 6y agoI'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.
- bobbylarrybobby 6y agoI 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
- pests 6y agoWhich 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.
- amenod 6y agoTrue, 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
- giantDinosaur 6y agoGoodness me that has potential to become something truly hideous.
- bryanrasmussen 6y agoI 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.
- vpzom 6y agoNo, if expressions can basically only be used with else, otherwise you have a type mismatch
- conradludgate 6y agoIt 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
- TheDong 6y agoIf 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&edition=2018&gist=1e7b3da5d8821ee99ee6d7f6936b0e21 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.
- bad-apple 6y agoNitpick: I'm pretty sure that "11..50" should be a "10..50".
- eximius 6y agoRust can also match on ranges which is perhaps the most idiomatic form for this.
- delta1 6y agofn calculate_tax(income: i32) -> i32 { match income { 0..=9 => 0, 10..=49 => 20, _ => 50, } } https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=64cd9c40d4783dc95dbdb38ae2824c55 https://play.rust-lang.org/?version=stable&mode=debug&editio...
- nyanpasu64 6y agoThis behaves differently for negative incomes, which are not prohibited by the i32 argument passed in (u32 cannot take on negative values).