There are a number of reasons why I do not think using a numbered placeholder variable shorthand like $0 would be a beneficial change.
First, one of the goals of the original if let shorthand proposal (SE-0345) was that its brevity encouraged clarity by not forcing a redeclaration of an already well-named variable.
Using numbered placeholder variables this way encourages code to use variables with names even less descriptive than proposal SE-0345 was trying to help developers avoid.
So, I think this sacrifices clarity over brevity.
Second, I think this would interact poorly with existing uses of $0, such as in closures:
if let customer.wishListItems {
return $0.map { ShoppingCartItem($0) }
}
Third, in multi-condition conditional statements, it makes the order of the statements very brittle:
if let customers.first, let dailyDeals.first {
// $0 refers to unwrapped customers.first
// $1 refers to unwrapped dailyDeals.first
}
If you then needed to refer to an optional value in the optional customer, as well as the customer, you might do something like:
// Assuming unwrapped $0 would be valid in subsequent conditions
if let customers.first, let $0.loyaltyClubNumber, let dailyDeals.first {
// $0 refers to unwrapped customers.first
// $1 now refers to customers.first.loyaltyClubNumber
// $2 now refers to unwrapped dailyDeals.first
}
Depending on the code in the body, there may be a fair amount of renaming of the numbered variables.
Note that with closures, the type of the closure includes the order and type of the arguments that become the numbered variables. When part of an API, these change fairly rarely, so this is much less of an issue for numbered arguments in closures.
Finally, I think the existing consistency between if let and guard let is very important.
The consistency allows developers to choose between using if let and guard let based on what is best for the flow of their code, not based on one construct having different or more capabilities than the other.
Adding $0 to only if let could lead developers to use if let even when guard let would lead to cleaner or more readable code, only because the shortcut variable was desired. It additionally would add to the cognitive load of keeping track of things that will work with an if let that wonāt work with a guard let.
So, I donāt think if let and guard let should diverge.
So, if this were added to if let, it should also be added to guard let. But, I think having the $0 variable work with guard let is problematic.
The existing named $0 in closures is typically used for closures with short bodies. I think that is also why thinking of using numbered placeholder variables is appealing for use in the body of an if statement.
With guard let however, the numbered variable persists for the lifetime of the containing scope. To remember which numbered variable is which, the developer needs to keep referring back to the earlier guard statements. Needing to tell $0, $1, and $2 apart further down in the body of a method with modest length does not promote clarity at the point of use.
This also brings up ordering issues. Very often developers will use separate guard statements to check for different conditions. I would imagine the numbered variables would need to be order-dependent and cumulative:
guard let customers.first else { print(āNo customer availableā); return }
guard let products.featuredProduct else { print(āNo featured productā); return }
// $0 refers to unwrapped customers.first
// $1 refers to unwrapped featuredProduct
Adding, removing, or reordering the guard statements makes the use of the placeholder variables very brittle.
So, I donāt think it makes sense to add this for guard let and I donāt think the benefit is strong enough to make if let condition behavior diverge from guard let condition behavior.
For these reasons I donāt think that using numbered placeholder variables would work well for this proposal.