I've had an idea floating around in my mind for a couple weeks now and would
like to find out what others think about it.
The basic idea is really simple. It introduces an `@option` parameter
attribute. Parameters with this attribute would behave like parameters with a
default value at the call site, however they would not actually have a default
value. Instead, the argument seen in the body would be an optional of the type
of the parameter value.
func foo(@option value: Int) {
// value has type Int? in the body of the function
let valueToUse = value ?? 42
}
At first glance it probably seems like this is of no value. Why not just
declare `value: Int? = nil`. Obviously it must bring something to the table to
be worth considering.
This idea first occurred to me while thinking about flexible memberwise
initialization. One of the use cases I have had in mind while writing that
proposal is a theoretical Swift version of UIKit that exposes all of its
appearance properties as memberwise initialization parameters with defaults
rather than just initializing the members to a default value. Obviously this
could lead to a very large stack frame that isn't really necessary. Using the
`@option` approach we can avoid the unnecessarily large stack frame.
Instead of always passing a value for every parameter the compiler would use a
single dynamic data structure containing the values of all `@option` arguments
provided at the call site. The layout of the data structure would be an
implementation detail of the language and would be part of the ABI. It would
contain a header of some kind indicating which parameters were actually
provided with arguments at the call site and any additional information
necessary to recover the value. In the body of the function, references to the
parameter value would be replaced with a lookup into the data structure which
returned an optional value of the type of the parameter.
Perhaps the most interesting thing about `@option` is that careful design of
the implementation might allow for `@option` parameters to be added or removed
from a function without breaking ABI compatibility:
1. When new parameters are added, existing callers will simply never provide
arguments and the implementation will see a nil optional value.
2. When parameters are removed, existing clients will continue to provide them
and the data structure will still be populated with them. The implmentation
will simply never look for the value. The function will behave as if the
parameter was still specified in the signature and simply not used. The client
would receive a compiler warning when compiling agains the newer SDK but
everything would continue to work without issue until they did so.
If this is possible `@option` parameters would enable more robust evolution for
functions containing parameters that may be omitted or have default values.
Another benefit of `@option` is that it provides better encapsulation of
default values because they do not appear in function and method signatures.
My understanding of the planned mechanism for default arguments is that any
changes to default parameter values will not be visible to clients until they
recompile against the new version of the library. If this is the case
`@option` would also provide additional control to library authors who may wish
to modify the default behavior of their implementation without breaking ABI.
Lastly, but potentially useful benefit of `@option` is that default argument
values do not allow a function to distinguish between the case when a caller
explicitly provides a value that happens to be the same as the default and the
case when no argument was provided. `@option` provides this information to the
body of the function.
Finally, an interesting observation: changing a parameter from having a default
value to `@option` or vice versa would break ABI but would be source-compatible.
I am very interested to hear whether others think this idea is worth pursuing
further or not.
Matthew
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution