To summarize, there's one ambiguous case we'd need to resolve:
func foo(_ x: Int, reportingOverflow)
func foo(_ x: Int, _ reportingOverflow: Bool)
let reportingOverflow = true
foo(5, reportingOverflow) // Ambiguous
One solution is to make trailing argument labels syntactic sugar for a
trailing void argument.
That would allow breaking ambiguity by specifying it explicitly:
foo(5, reportingOverflow: ())
A related issue is the call-site ambiguity for the reader (less of a
problem if Xcode highlighted argument labels).
Vladimir suggested that an alternative might be to use a leading colon to
There is another alternative I can think of, based on feature that was
discussed at some point of time the list: anonymous enums, i.e. when you
can declare enum inside function declaration, when such enum has almost
no meaning outside of the function call.
I.e. something like this:
func foo(_ x: Int, with: (.reportingOverflow))
foo(10, with:.reportingOverflow)
I.e. you can have more than one enum case here if you want:
func foo(_ x: Int, with: (.reportingOverflow, .otherFlag))
// IIRC, such syntax was discussed:
// func foo(_ x: Int, with: (.reportingOverflow | .otherFlag))
foo(10, with:.otherFlag)
But such anonymous enums were considered as bad idea during the
discussion, so…
Yeah, I was one of the ones who liked the idea but it never seemed to get
much traction unfortunately.
[offtopic]
If I remember correctly, *one* of the objections was about the syntax(.one|.two|.three), but currently I think this could be solved without '|' characters, just using the comma. Like
func foo(arg: (.one,.two,.three), arg2: Int) {}
...
foo(arg: .two, 10)
...
let opt : (.one,.two,.three) = .one
foo(arg: opt, 10)
..
let opt : (.one,.two,.four) = .one
foo(arg: opt, 10) // ERROR: Anonymous enum is not the same. Expected (.one,.two,.three), but have (.one,.two,.four)
...
let opt : (.one,.two,.three) = .two
print(type(of:opt)) // AnonymousEnumOneTwoThree
print(type(of:opt)) //or: enum(.one,.two,.three) //or other variant
Sad that this feature was not supported.
[/offtopic]
Part of the problem though with using enums to select methods is that it's
not immediately obvious what they're doing; if you look at the signature
for a method you see a type, then have to investigate what it is and find
it only has one case, which is confusing. Documentation then needs to fill
in all the gaps to explain that it will only ever have one case (e.g- it's
not an enum that may be expanded with more options in future), and that's
it's for selecting methods. A single-case ad-hoc enum could be a bit
clearer, but it's still more of a workaround.
I think having a proper language feature is still the way to go, as it can
be more obvious at the function declaration that it's something different,
since it would be an untyped parameter.
You mentioned another possibility of putting the extra label after the
function, and I've been thinking about that as well, because the
interesting thing about that is it could be thought of as a kind of label
on the return type.
func adding(_ other:Self) -> Self
func adding(_ other:Self):reportingOverflow -> (Self, Bool)
let resultOnly = a.adding(b)
let resultReportingOverflow = a.adding(b):reportingOverflow
You did say it looks a bit like an operation on the result, but I suppose
another way of thinking about it is that until you set (or omit)
:reportingOverflow then you're actually calling *both* methods with two
possible results, and by adding that you tell Swift which one you want. It
could be a very neat thing to use as well within modern auto-complete; type
out the method at which point you can either hit space to move onto
something else, hit period to call a method on the result, or hit colon to
narrow down the result to something more specific.
Ack, I think I'm confusing myself now as to which solution I prefer. Having
the trailing label *after* the function call does have merits as well.
Weird idea, why not have function name just after arguments block, without any separator:
func adding(_ other:Self) -> Self
func adding(_ other:Self)reportingOverflow -> (Self, Bool)
let resultOnly = a.adding(b)
let resultReportingOverflow = a.adding(b)reportingOverflow
Also we should think about referenses to such function:
adding(_:) // ok
addint(_::reportingOverflow) // is it clear that we have 1 argument and reportingOverflow is a part of the function name?
or we should use in this case
addint(_:reportingOverflow) //?
addint(_:)reportingOverflow // seems like very clear
But again, I *do* believe such syntax improvements will not be approved by core team(and most likely by the community). Is it worth to discuss this?
···
On 23.02.2017 17:35, Haravikk wrote:
On 23 Feb 2017, at 12:49, Vladimir.S <svabox@gmail.com >> <mailto:svabox@gmail.com>> wrote:
On 23.02.2017 14:17, Haravikk wrote:
On 22 Feb 2017, at 21:25, Patrick Pijnappel <patrickpijnappel@gmail.com >>>> <mailto:patrickpijnappel@gmail.com> >>>> <mailto:patrickpijnappel@gmail.com>> wrote: