4 ms·
> Everyone parrots the same "different semantics" excuse never bothering to ask why. It's like you didn't even read my comment, I gave a reasoned answer why it
by skohan 6y ago
> Everyone parrots the same "different semantics" excuse never bothering to ask why.
It's like you didn't even read my comment, I gave a reasoned answer why it's different. It gives a queue to the user that the condition must be met, or else there will be an early return.
The example you gave is also not equivalent - here you have:
guard X else { /* branch A */ }
// Branch B
And here you have:
if X is not null {
// Branch B
}
// Branch A
The problem with your argument is that you are taking a subjective preference - that magical unwrapping via if-statements is the best form of unwrapping - and stating it as if it is an objective fact. You haven't actually given any arguments for why guard is an inferior approach beyond basically saying: just look at it, it's bad language design. Why is it bad?
> It won't cause issues if the language is actually properly designed. Because the variables you'll use will not checked for nullability in this case. And even Java will warn you with "potentially null value". But Swift can't do that without a `guard` statement.
Again, it's not a question of proper/improper design or a failure of the compiler. The designers of swift made a conscious decision to provide exactly 3 ways to unwrap an optional:
1) the force unwrap `!` operator,
2) the `if let` statement,
3) the `guard let` statement
Just because that is not the exact design you would prefer does not make it a bad design.
You're also ignoring the uses for `guard` beyond null checking. For instance, if I wanted to check that my arguments are within a certain bounds, I could do something like this:
func foo(x: Int) -> Int {
guard x >= 0, x <= 42 else { return 0 }
return 2*x
}
This has nothing to do with "manually tell[ing] the compiler to do a nullability check ... because the compiler and the type checker are just not good enough" - it's about having an explicit language construct to signal that you do not want to continue with the logic of this function if the condition is not met.
> Yes, you do. You wrap it in a guard statement, assign a variable to itself, and poof, magic, it's suddenly unwrapped.
These are actually very different things.
In this statement:
if x == nil { ... }
you are taking the conditional (`x == nil`) and giving it this magic side-effect that once it's executed, a new variable of a separate type is created and will replace `x` until the end of execution. Every other conditional simply evaluates to a boolean, so why should this one special case have this side effect where it's also declaring and assigning a new variable?
To contrast that with the statement which bothers you so much aesthetically:
guard let self = self else { return }
Here the `let <identifier> = <value>` denotes the fact that you are declaring and assigning a new variable here, which is why the type change can take place. It happens to have the same name as the previous `self`, but every aspect of this is consistent with the rules of the language, and there is no special case being created here.
You may not like it, and that's fine, but your personal taste does not reflect an objective truth about language design. Tens of thousands of swift developers around the world are able to understand the motivation for, and benefits of `guard` statements just fine. If you are bizarrely confused or angered by them, it does not mean they are categorically bad.