[swift-evolution] Closures from methods with default args

Xiaodi Wu xiaodi.wu at gmail.com
Thu Jan 19 23:26:12 CST 2017


Hmm, I don't recall the earlier discussion, but IMO, Charlie's proposal is
pretty sensible. Seems backwards to adding much broader things like default
argument support for protocols motivated by a use case that should Just
Work(TM).

I recall that once upon a time Chris Lattner declared that the core team
was perfectly willing to implement difficult things if it improved the
Swift user experience. Here, it seems either this is something that *can*
be made to just work in the default arguments handling department, and then
it should be, or it can't, and then the closure syntax is a fairly obvious
and workable if not pretty workaround. No point in designing features as a
workaround for something that has both an obvious ideal solution and a
current workaround.
On Thu, Jan 19, 2017 at 23:07 David Sweeris via swift-evolution <
swift-evolution at swift.org> wrote:

>
> On Jan 9, 2017, at 02:13, Charlie Monroe via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I came across something that I'm not sure it's a bug or by design and if
> it's by design, whether this should be discussed here.
>
> Example:
>
> class Foo {
>     init(number: Int) { /* ... */ }
> }
>
> let closure = Foo.init(number:) // (Int) -> Foo
> [1, 2, 3].map(closure) // [Foo, Foo, Foo]
>
> This works great until the initializer gets a default argument:
>
> class Foo {
>     init(number: Int, string: String = "") { /* ... */ }
> }
>
> // Error: Foo has no member init(number:)
> let closure = Foo.init(number:)
>
> I was wondering if we could get closures to methods without the default
> arguments. Currently, this needs to be worked around by e.g. creating a
> second closure that invokes the method without the default arguments:
>
> let closure: (Int) -> Foo = { Foo(number: $0) }
>
> But to me it seems like something that should work "out of the box".
>
> Thoughts?
>
>
> IIRC, this issue was raised a while ago, and as best as I recall the gist
> of the answer was that default arguments are implemented at the call site,
> and because of that you can't pass a function with default arguments to
> something expecting a function with fewer arguments even though the two
> calls look identical in the source code.
>
> It causes other issues, too. For instance, if we have
>     protocol Initable { init() }
> And
>     struct Foo { init(_ x: Int = 0) {} }
> We're left in an odd situation where `Foo`  can't meaningfully conform to
> `Initable` because while "init(_: Int = 0)" is not the same as "init()", if
> you add a "init()" to `Foo`
> you'll get an ambiguous somethingerather error because there's no
> mechanism for the compiler to know whether you want the actual "0 argument"
> function or the "1 argument with 1 default value" function.
>
> Aside from re-architecting the default argument system (which I'm not even
> sure is possible, let alone a good idea), I think I see couple ways forward
> for the protocol conformance issue. Both have downsides, though.
>
> 1) Require any potentially conflicting protocol functions to be in an
> extension so the compiler knows what's going on, have "Foo()" call the one
> defined in the type, and use "(Foo as Initable)()" for the protocol version
> defined in an extension. This could get real confusing real fast if people
> don't realize there's two functions with, as far as they can tell, the same
> signature.
>
> 2) Add default argument support to protocols. The syntax that makes sense
> to me would be something like
>     protocol Bar {
>         func baz(_: Int = _)
>     }
> On the downside, I suspect this would necessarily add a phantom "Self or
> associated type requirement" so that the compiler could have a way to get
> at each implementation's default value. It's not ideal... You'd get an
> error kinda out of the blue if you tried to use the function
> non-generically, but at least you couldn't have a function change out from
> under you.
>
> - Dave Sweeris
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170120/ff5dd4b7/attachment.html>


More information about the swift-evolution mailing list