[Swift-devel] Keyword Args and Overloading

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


Also, KWArgsBeforeOptArgs should be PosArgsBeforeKWArgs - wasn't thinking
clearly

- Tim

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

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


More information about the Swift-devel mailing list