[swift-evolution] [Pre-pitch] Conditional default arguments

Tony Allevato tony.allevato at gmail.com
Tue Nov 28 10:06:33 CST 2017

On Mon, Nov 27, 2017 at 10:32 PM Slava Pestov <spestov at apple.com> wrote:

> Hi Tony,
> So if my understanding is correct, the basic proposal is the following:
> func id<T>(t: T ?= T.defaultValue) { return t }
> extension Int { static var defaultValue = 0 }
> extension String { static var defaultValue = “” }
> id() as Int // returns 0
> id() as String // returns “”
> id() as SomeRandomType // fails to type check — no default argument
> I don’t understand what would happen if the caller is itself generic
> though, for example:
> callsID<T>(_ t: T) {
>   _ = id() as T
> }
> It appears that body of callsID() itself cannot type check without
> knowledge of the concrete T that will be used with this function.

Thanks for bringing up this example, Slava.

Unless I'm misunderstanding, the issue you're describing is inherent to the
*problem* described in the original post, not to any specific hypothetical
syntax for adding the default arguments, correct? In other words, if this
was written using extensions as can be done today:

struct Foo<T> {
  func id(t: T) -> T { return t }

extension Foo where T == Void {
  func id() -> T { return () }

extension Foo where T == Int {
  func id() -> T { return 0 }

callsID<T>(_ t: T) {
  _ = Foo().id() as T    // mark

The compiler would still reject the marked line because there's no
guarantee that T is one of the types that has the necessary overload.

But now that you've mentioned it, it does have me thinking that this
problem might be better left to extensions. In one sense, default arguments
are a kind of "overload synthesis", but on the other hand, there's an
expectation that the default value expression is of a single type (or set
of related types) known at compile time. Even if it's generic, it still
must be expressed in terms of whatever constraints are present on that
generic type—you can't use a disjunction of types, but instead have to have
a common protocol that would provide some operation.

> Slava
> On Nov 27, 2017, at 4:10 PM, Tony Allevato via swift-evolution <
> swift-evolution at swift.org> wrote:
> I totally agree that that's a good rule in general—I'm not 100%
> comfortable making an exception to it for this, but I wanted to start a
> discussion about a different approach than had been considered so far.
> The idea of forcing the user to acknowledge the explicitness of SFINAE
> with a strawman syntax `=?` instead of `=` was a thought experiment to
> bridge the wild-west-C++ world of templates and Swift's stricter generics,
> but I can definitely understand if even that kind of approach is something
> that the core team (who are far more familiar with the C++ side of that
> coin than I am) doesn't wish to support. As was pointed out, it's not
> something Swift supports anywhere else today.
> If we look at it from that point of view, where such a semantic treatment
> of generics would not be supported, I think it becomes a lot harder to
> rationalize treating this as "default arguments". What you really do have
> (and what writing it as constrained extensions makes clear) is additional
> overloads, because they only apply to certain subsets of types. If that's
> the case, maybe it's the wrong approach to try to turn overloads into
> "partial default values".
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171128/68f7caf0/attachment.html>

More information about the swift-evolution mailing list