[Swift-devel] Keyword Args and Overloading

Tim Armstrong tim.g.armstrong at gmail.com
Sat Feb 7 16:10:08 CST 2015


Hi All,

  So we had a bunch of useful discussion about what we wanted to support in
functions.  There was a pretty clear decision to only support overloading
for library functions at this stage, but I think a few things were left
unspecified, since there are a lot of potential variations.


To pin it down, I'm going to attempt to define some terms and precisely
talk about what design decision we're making.

Definitions
========

Function definition: a single function definition that specifies the types
and names of arguments, plus info for any additional features about
arguments
Composite functions: functions with a Swift body
Function callsite: a place in the program where the function is called with
a list of arguments.  In general, we can have f(1, 2, 3, argname1=4,
argname2=5)
Overloaded function definitions (Overloads): where multiple function
definitions with the same name exist, and they are disambiguated at the
function callsite based on the callsite arguments

Callsite argument categories:
Positional Arguments (PosArgs) - when the the caller only specifies
position.  e.g. f(1,2,3)
Keyword Arguments (KWArgs) - when the callsite specifies the name of the
argument, e.g. f(x=1, y=2).  This allows them to be specified out of order
or with some omitted

Function definition argument categories:
Required Arguments(ReqArgs) - arguments that are required
Variadic Arguments (VarArgs) - the last argument in the function definition
can match 0 or more PosArgs
Optional Arguments (OptArgs) - when a default value is provided for an
argument, e.g. f(arg=2)
Polymorphic Arguments (PolyArgs) - when a argument in the function
definition can be one of set of types (e.g. wildcard type, type variables,
union types)

Matching rules (I've marked the ones up for discussion with a ??? and
uncontroversial ones with :)):
PosArgs -> ReqArgs - :)
PosArgs -> VarArgs - :)
PosArgs -> OptArgs - ???
KWArgs -> ReqArgs - ???
KWArgs -> VarArgs - ???
KWArgs -> OptArgs - :)

Restrictions
=========
Overall restrictions that I think we agree on, for now:
* VarArgs and OptArgs cannot be used in same function definition.
* Any OptArgs must be followed only by other OptArgs
* VarArgs cannot be used in composite function definitions
* PolyArgs cannot be used in composite function definitions

So now I think there are a few somewhat different ways we can allow the
other features to be combined.  The baseline features, that I will assume
for the rest are:

  ReqArgs + PosArgs. + VarArgs + (PosArgs -> ReqArgs) + (PosArgs -> VarArgs)

My understanding of the current states of Swift/T and Swift/K are:

  T -VarArgs|OptArgs + PolyArgs
  K -VarArgs|OptArgs + PolyArgs (sorta) + KWArgs + (KWArgs -> OptArgs)

If we want to extend things, first, this would be the attempt to support
everything in combination.

  PolyArgs + VarArgs|OptArgs + KWArgs +(PosArgs -> OptArgs) + (KWArgs ->
ReqArgs) + (KWArgs -> VarArgs) + Overloading

I think we agree that this is not reasonable to implement.  I'm not totally
clear on which subset we are planning to support though.  One restriction
that seems reasonable is to disallow the combination of PolyArgs and
Overloading:

 VarArgs|OptArgs + PolyArgs|Overloading + KWArgs +(PosArgs -> OptArgs) +
(KWArgs -> ReqArgs) + (KWArgs -> VarArgs)

Maybe we also don't really need (KWArgs -> ReqArgs) + (KWArgs -> VarArgs) -
they seem marginally useful at best.  I think it's also reasonable to
restrict matching so that KWArgs are always matched before PosArgs.  I.e.
f(1, x=1) doesn't match f(int x=0, int y=0) .  I'll call this
KWArgsBeforeOptArgs.  This corresponds to the algorithm "Match n
positionals with first n args, then resolve KWArgs to remaining OptArgs"

That would leave:

 VarArgs|OptArgs + PolyArgs|Overloading + KWArgs +(PosArgs -> OptArgs) -
KWArgsBeforeOptArgs

I think resolving overloads here is still a little complex because we need
to consider multiple ways to match keyword arguments to positional
arguments. It's also difficult to work out (in the compiler or in the
programmer's head) if two overloaded definitions may potentially conflict
because the matching of callsite args to definition arguments is complex. I
think the possibility exists if the ReqArgs of one overload is a prefix of
the ReqArgs of the another overload and there's some overlap in keyword arg
names.  I'd imagine in many situations where people might want to use
OptArgs+Overloading, then this is a possibility.

One option (I think Swift/K does this) is to strictly match PosArgs to
ReqArgs and KWArgs to OptArgs.

  VarArgs|OptArgs + PolyArgs|Overloading  + KWArgs

I think it is probably not too difficult to resolve overloads with KWArgs
in this situation. The restriction {positionals1} = {positionals2} or
{keywords1} ∩ {keywords2} != 0 that Mihael proposed on overloading does
help things here. I still find this choice a little unsatisfying because
programmers often would prefer to provide optional arguments positionally.

Another option is to discards KWArgs, leaving us:

  VarArgs|Optargs + PolyArgs|Overloading + (PosArgs -> OptArgs) -
KWArgsBeforeOptArgs

I think we agree that KWArgs are a nice feature that we'd like to have, so
that's not great either.  Maybe we can disallow OptArgs for overloads
though - it seems like in most situations you would use one or the other,
not both.  We could potentially
This would give us:

 VarArgs|OptArgs + PolyArgs + KWArgs +(PosArgs -> OptArgs) -
KWArgsBeforeOptArgs
 VarArgs + PolyArgs|Overloading + KWArgs +(PosArgs -> OptArgs) -
KWArgsBeforeOptArgs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/swift-devel/attachments/20150207/9db22a90/attachment.html>


More information about the Swift-devel mailing list