Protocol methods should accept default arguments

Hi list,

I propose that methods defined in protocols should accept default arguments. This could help remove the need for method families where only one parameter is essential, but others are often used.

For example:

protocol Datastore {
  func executeQuery(query: String)
  func executeQuery(query: String, usingParameters: [Any])
  func executeQuery(query: String, usingParameters: [Any], logType: LogType)
  func executeQuery(query: String, usingParameters: [Any], logType: LogType, completionHandler:ClosureOfSomeSort)
}

Where typically the implementing object funnels the first three methods through to the final, more verbose method.

This could be shortened to:

protocol Database {
  func executeQuery(query: String, usingParameters: [Any] = , logType: LogType = .NotLogged completionHandler:ClosureOfSomeSort? = nil)
}

Advantages:
- Only one method to implement
- Less to document, less cluttered interface
- Prevent objects adopting the protocol from using different default values
- Prevent objects from implementing similar methods in the family differently - fewer code paths to inspect, less confusion over behaviour since no argument values are hidden

This fits in well with the parameters section of the Swift API design page: https://swift.org/documentation/api-design-guidelines.html#parameters

What do you think?

Regards,

Ben Barnett

1 Like

I ran into a situation like this in my own code and thought the same before I realized that the protocol only needs the single function that takes all of the parameters (with no need for defaults) and convenience variants can provide default values by implementing them in a protocol extension.

l8r
Sean

···

On Dec 4, 2015, at 10:31 AM, Ben <ben_cocoa_dev_list@yahoo.co.uk> wrote:

Hi list,

I propose that methods defined in protocols should accept default arguments. This could help remove the need for method families where only one parameter is essential, but others are often used.

For example:

protocol Datastore {
  func executeQuery(query: String)
  func executeQuery(query: String, usingParameters: [Any])
  func executeQuery(query: String, usingParameters: [Any], logType: LogType)
  func executeQuery(query: String, usingParameters: [Any], logType: LogType, completionHandler:ClosureOfSomeSort)
}

Where typically the implementing object funnels the first three methods through to the final, more verbose method.

This could be shortened to:

protocol Database {
  func executeQuery(query: String, usingParameters: [Any] = , logType: LogType = .NotLogged completionHandler:ClosureOfSomeSort? = nil)
}

Advantages:
- Only one method to implement
- Less to document, less cluttered interface
- Prevent objects adopting the protocol from using different default values
- Prevent objects from implementing similar methods in the family differently - fewer code paths to inspect, less confusion over behaviour since no argument values are hidden

This fits in well with the parameters section of the Swift API design page: https://swift.org/documentation/api-design-guidelines.html#parameters

What do you think?

Regards,

Ben Barnett

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

Default parameters are in my opinion an implementation detail and should be always handled by the conforming type. What can be done here is only declare the 4th method in the protocol and create a protocol extension with default forwarding.

···

On 04 Dec 2015, at 17:31, Ben <ben_cocoa_dev_list@yahoo.co.uk> wrote:

Hi list,

I propose that methods defined in protocols should accept default arguments. This could help remove the need for method families where only one parameter is essential, but others are often used.

For example:

protocol Datastore {
  func executeQuery(query: String)
  func executeQuery(query: String, usingParameters: [Any])
  func executeQuery(query: String, usingParameters: [Any], logType: LogType)
  func executeQuery(query: String, usingParameters: [Any], logType: LogType, completionHandler:ClosureOfSomeSort)
}

Where typically the implementing object funnels the first three methods through to the final, more verbose method.

This could be shortened to:

protocol Database {
  func executeQuery(query: String, usingParameters: [Any] = , logType: LogType = .NotLogged completionHandler:ClosureOfSomeSort? = nil)
}

Advantages:
- Only one method to implement
- Less to document, less cluttered interface
- Prevent objects adopting the protocol from using different default values
- Prevent objects from implementing similar methods in the family differently - fewer code paths to inspect, less confusion over behaviour since no argument values are hidden

This fits in well with the parameters section of the Swift API design page: https://swift.org/documentation/api-design-guidelines.html#parameters

What do you think?

Regards,

Ben Barnett

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

Thank you Felix and Sean for the advice. I am happy to cautiously withdraw my suggestion, since this is a mostly acceptable workaround. The only hiccup appears to be with where inline documentation should be placed to have it appear in Xcode (in the extension, not the original protocol). I will think further and perhaps file a radar for Xcode later.

Incidentally, having explored the mailing lists further it seems that stuff like my original post should start in the swift-users list then works it's way over here. Would that be correct? I don't want to be extra noise in the wrong place.

- Ben

···

On 4 Dec 2015, at 16:37, Felix Gabel <felix.gabel@me.com> wrote:

Default parameters are in my opinion an implementation detail and should be always handled by the conforming type. What can be done here is only declare the 4th method in the protocol and create a protocol extension with default forwarding.

On 04 Dec 2015, at 17:31, Ben <ben_cocoa_dev_list@yahoo.co.uk <mailto:ben_cocoa_dev_list@yahoo.co.uk>> wrote:

Hi list,

I propose that methods defined in protocols should accept default arguments. This could help remove the need for method families where only one parameter is essential, but others are often used.

For example:

protocol Datastore {
  func executeQuery(query: String)
  func executeQuery(query: String, usingParameters: [Any])
  func executeQuery(query: String, usingParameters: [Any], logType: LogType)
  func executeQuery(query: String, usingParameters: [Any], logType: LogType, completionHandler:ClosureOfSomeSort)
}

Where typically the implementing object funnels the first three methods through to the final, more verbose method.

This could be shortened to:

protocol Database {
  func executeQuery(query: String, usingParameters: [Any] = , logType: LogType = .NotLogged completionHandler:ClosureOfSomeSort? = nil)
}

Advantages:
- Only one method to implement
- Less to document, less cluttered interface
- Prevent objects adopting the protocol from using different default values
- Prevent objects from implementing similar methods in the family differently - fewer code paths to inspect, less confusion over behaviour since no argument values are hidden

This fits in well with the parameters section of the Swift API design page: https://swift.org/documentation/api-design-guidelines.html#parameters

What do you think?

Regards,

Ben Barnett

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

Can you explain why? I've just run into this myself, and after 20 minutes of searching, I've found workaround, but no answer why. it seems like a perfectly reasonable thing to want to be able to do:

protocol
ToolComponentRepository : Repository
{
    func find(for inVendorID: UUID, page inPage: Int? = nil, pageSize inPageSize: Int = 10) -> EventLoopFuture<[ToolComponent]>
}

Sure, I can make an extension and implement this explicitly, but why create the restriction in the first place? Why have default arguments at all?

@JetForMe This thread was created almost five years ago. Please avoid resurrecting these old threads, as participants who haven't registered for the Discourse forums get automatic emails that they can't unsubscribe from.

Perhaps that should be spelled out in the little warning about old threads. It seems better to me to resurrect an existing thread on the topic than to make a new one; makes it harder for someone searching the forums to find all the relevant discussion.

Better would be to fix it such that participants in old discussions who haven't registered simply don't get notified.

4 Likes

The forum has existed for long enough now: it would be a good adjustment to stop notifying non-registered participants.

1 Like