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
}
}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
}
} 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...¯\_(ツ)_/¯
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.Nested ternary if statements scare me from my PHP days, and noticed inlined closures can at times be harder to grok at a glance.
Cond1 // if this
? Result1 // return this
: cond2 // else if this
? Result2 // return this
: cond3 // else if this
? Result3 // return this
: ResultElse // else return this Cond1 // if this
? Result1 // return this
: cond2 // else if this
? Result2 // return this
: cond3 // else if this
? Result3 // return this
: ResultElse // else return this 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.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.
Instead of:
int salary = isEmployed() ? 2000 : 0
I prefer:
int salary = 2000 if isEmployed() else 0
func calculate_tax(income):
return 0 if income < 10 else 20 if income < 50 else 50 let foo = if is_employed() { 2000 } else { 0 } 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. let foo = match () {
_ if x <= 0 => 0,
_ if something_else > 50 => 9000,
_ => 42,
};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.
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.
https://play.rust-lang.org/?version=nightly&mode=release&edi...