[Swift-devel] Keyword Args and Overloading

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


Oops, hit send before I finished typing.  The last bit should be:

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

I think we could revisit the combination of Overloading + OptArgs later and
support it only for cases where it was simple to resolve, but this seems
like a good starting point.

Also, we would only be supporting some of these features for library
functions initially, meaning the use cases are more constrained, but I have
to write the typechecking algorithms for library functions anyway.

Anyway, so I was hoping that we'd be able to agree on one of the options
and have it concretely stated so that we're implementing the same thing in
T and K.  I prefer the last alternative, but there are other reasonable
ones and it'd be good to get everyone's inputs and thoughts.

- Tim

On Sat, Feb 7, 2015 at 4:10 PM, Tim Armstrong <tim.g.armstrong at gmail.com>
wrote:

> 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/416cdb09/attachment.html>


More information about the Swift-devel mailing list