What is your evaluation of the proposal?
-1, on the basis of use being a potential anti-pattern, and the spec focusing on the benefit of a terser syntax over possible uses.
If there are additional uses outside the proposal, this evaluation may change.
Is the problem being addressed significant enough to warrant a change to Swift?
Not as described.
“??” is described as the nil coalescing operator. It is defined as the following function:
public func ??<T>(optional: T?, @autoclosure defaultValue: () throws -> T) rethrows -> T
The purpose of the nil coalescing operator is defined as follows by the Swift Programming Language book
“The nil coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil. The expression a is always of an optional type. The expression b must match the type that is stored inside a.”
This operator has thus two core properties:
1. it allows another mechanism to deal with nil values, by specifying an alternate value to use in the nil case
2. as either the value or the alternate is non-nil, it casts off optionality
This operator does not do the second. It allows you to apply a value in the nil case, but the resulting value is still an optional. As such, I fear the usefulness of the “??=“ operator is greatly diminished.
Note also that unlike other operators with inout equivalents like addition, the type of the left-hand input and the output are not the same in “??” due to the missing safe casting off of optionality.
Does this proposal fit well with the feel and direction of Swift?
The example given by the proposal is as follows:
really.long.lvalue[expression] = really.long.lvalue[expression] ?? ""
In this case, you are setting a default value of “” to an optional target within a long expression.
However, it is unclear why the original expression allowed nil, or why setting this value to “” is an improvement.
To counter, some existing usage:
let userDefaults = NSUserDefaults.standardUserDefaults()
let repeatCount = userDefaults.valueForKey("repeatCount") as? Int ?? 4
for attempt in 0..<repeatCount {
// ...
}
The for loop only works because repeatCount is non-optional. Assigning the value back into the expression would mutate the original value, but would still require one to cast off the optionality of the value.
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
As mentioned, Ruby has a similar behavior. Other than the “false” and “nil” literal values, everything evaluates as true. The || and && operators preserve the values of the lhs and rhs arguments.
1 && 2 # is 2
1 || 2 # is 1
nil || 2 # is 2
As such, ||= can be used for such a default assignment system.
However, ruby does not have optionality. All libraries must take into account the possibility of sending nil in for a value. As such, it is not influenced by the limitations of this proposal.
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
In-between a reading and a study.
-DW