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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to