> On Nov 25, 2017, at 1:28 PM, Tony Allevato via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> On Fri, Nov 24, 2017 at 7:18 PM Xiaodi Wu via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> 
> 
> 
> It's kludgy, but we could have something like:
> 
> ```
> @defaultArgument(configuration = (), where R.Configuration == Void)
> @defaultArgument(actionHandler = { _ in }, where R.Action == Never)
> func makeResource(with configuration: R.Configuration, actionHandler: 
> @escaping (R.Action) -> Void) -> R { ... }
> ```
> 
> I don't like that we'd be setting a default argument on something lexically 
> before even encountering it in the declaration, but it's serviceable.
> 
> 
> What if we could take advantage of the fact that you can have non-constant 
> expressions in default arguments? Overload resolution could already do most 
> of the job—what we need on top of that is a way for the author to say that 
> “if no overload matches, then it’s not an error—just don’t have a default 
> argument in that case”. Something like SFINAE in C++, but more explicit.
> 
> I’m imagining something like this:
> 
> func defaultConfiguration() -> Void {
>   return ()
> }
> 
> func defaultActionHandler() -> (Never) -> Void {
>   return { _ in }
> }
> 
> struct ResourceDescription<R: Resource> {
>   func makeResource(
>     with configuration: R.Configuration =? defaultConfiguration(),
>     actionHandler: @escaping (R.Action) -> Void =? defaultActionHandler()
>   ) -> R {
>     // create a resource using the provided configuration
>     // connect the action handler
>     // return the resource
>   }
> }
> The main difference here is the strawman =? syntax, which would indicate that 
> “the default argument exists if there is a way the RHS can be satisfied for 
> some instances of the generic arguments; otherwise, there is no default”, 
> instead of today’s behavior where it would be an error. There could be 
> multiple overloads of defaultConfiguration and defaultActionHandler (even 
> ones that are themselves generic) and it would do the right thing when there 
> are matches and when there aren’t.
> 
> I like this approach because it mostly takes advantage of existing language 
> features and is fairly lightweight in terms of how it’s expressed in code 
> compared to regular default arguments—we’d just need to design the new 
> operator and type-checker logic around it.
> 
This is an interesting approach.  One advantage to something in this direction 
is that it could support defining different defaults for the same argument 
under different constraints by overloading the default argument factories on 
their return type.

One concern I have is that it doesn’t allows us to clearly define under which 
constraints a default argument is available.  I suspect this might be 
problematic especially for public interfaces where source compatibility is a 
concern.  

I think I prefer Xiaodi’s suggestion for that reason.  His approach could also 
support multiple defaults for the same parameter as long as the constraints are 
not allowed to overlap (overlapping constraints would result in ambiguity 
similar to ambiguous overload resolution) or an explicit argument is required 
if they do.

> 
> 
> 
> 
> 
> On Fri, Nov 24, 2017 at 8:36 PM, T.J. Usiyan via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> I am all for this. are many types where there is an obvious 'zero' or 
> 'default' value and the ability to express "use that when possible" without 
> an overload is welcome.
> 
> 
> The best thing that I can think of right now, in terms of syntax, is actually 
> using @overload
> 
> ```
> struct ResourceDescription<R: Resource> {
> 
>   func makeResource(with configuration: R.Configuration, actionHandler: 
> @escaping (R.Action) -> Void) -> R 
>  @overload(R.Configuration == Void) func makeResource(actionHandler: 
> @escaping (R.Action) -> Void) -> R
> @overload(R.Action == Never)  func makeResource(with configuration: 
> R.Configuration) -> R
> {
>     // create a resource using the provided configuration
>     // connect the action handler
>     // return the resource
>   }
> }
> ```
> 
> 
> This isn't great though…
> 
> On Fri, Nov 24, 2017 at 6:11 PM, Matthew Johnson via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> As mentioned in my prior message, I currently have a PR open to update the 
> generics manifesto (https://github.com/apple/swift/pull/13012 
> <https://github.com/apple/swift/pull/13012>).  I removed one topic from that 
> update at Doug Gregor’s request that it be discussed on the list first.  
> 
> The idea is to add the ability to make default arguments conditional (i.e. 
> depend on generic constraints).  It is currently possible to emulate 
> conditional default arguments using an overload set.  This is verbose, 
> especially when several arguments are involved.  Here is an example use case 
> using the overload method to emulate this feature:
> 
> ```swift
> protocol Resource {
>   associatedtype Configuration
>   associatedtype Action
> }
> struct ResourceDescription<R: Resource> {
>   func makeResource(with configuration: R.Configuration, actionHandler: 
> @escaping (R.Action) -> Void) -> R {
>     // create a resource using the provided configuration
>     // connect the action handler
>     // return the resource
>   }
> }
> 
> extension ResourceDescription where R.Configuration == Void {
>   func makeResource(actionHandler: @escaping (R.Action) -> Void) -> R {
>     return makeResource(with: (), actionHandler: actionHandler)
>   }
> }
> 
> extension ResourceDescription where R.Action == Never {
>   func makeResource(with configuration: R.Configuration) -> R {
>     return makeResource(with: configuration, actionHandler: { _ in })
>   }
> }
> 
> extension ResourceDescription where R.Configuration == Void, R.Action == 
> Never {
>   func makeResource() -> R {
>     return makeResource(with: (), actionHandler: { _ in })
>   }
> }
> 
> ```
> 
> Adding language support for defining these more directly would eliminate a 
> lot of boilerplate and reduce the need for overloads.  Doug mentioned that it 
> may also help simplify associated type inference 
> (https://github.com/apple/swift/pull/13012#discussion_r152124535 
> <https://github.com/apple/swift/pull/13012#discussion_r152124535>).
> 
> The reason that I call this a pre-pitch and one reason Doug requested it be 
> discussed on list is that I haven’t thought of a good way to express this 
> syntactically.  I am interested in hearing general feedback on the idea.  I 
> am also looking for syntax suggestions.
> 
> Matthew
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to