-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: implement #4916, keyword args as dictionary #21915
Conversation
Highly-biased benchmark: Before:
after:
|
No this has no effect on type inference. |
I have some unpublished (and unpolished) code that actually exploited the fact that you could pass in duplicate keyword arguments; just to confirm, this would not allow duplicate keyword args, right? Not saying we shouldn't do this, but just confirming. |
You're still allowed to pass duplicate keyword arguments, but they get de-duplicated. However the implementation of |
Cool! I've been playing with the idea of using a strongly-typed immutable dictionary for the keyword arguments, with a proof-of-principle demonstration using macros at the definition and call sites (this is still early WIP but I'm confident it would work) with the idea that lowering could implement the macro behavior automatically... So I think we could have all the things (dictionary structure for the varargs (rest?) keywords, plus type stability) without too much fuss - the main difference to this being using a strongly-typed dict instead of |
Yes, I think it's likely we will eventually use whatever form of built-in NamedTuple type we end up with for this. Here it gets interesting, since from my experience with NamedTuples (and also true of namedtuples in python), the elements should just be the values, and not key=>value pairs, since the names are part of the structure (or type), and not part of the data. That raises the question of what the interface for keyword argument providers should be. Currently we expect them to be (1) iterable, and (2) generate elements that can be iterated to yield 2 values (a name Symbol and a value). That works, but it seems ad-hoc and inelegant to me, and doesn't fit well with more strongly-typed containers where the type of the value can depend on the name. Anybody have any ideas? |
f138010
to
98258ae
Compare
Well, there could be a way to iterate over objects by field name? Maybe
|
I'm not sure if this is a good idea, but since this PR suggests using an https://gist.github.com/ajkeller34/9987cfcc53660cfbb5349965fc6a2a52 Then again, the type signatures become pretty ungainly, so the elegance criterion may not be satisfied. |
Thanks Andrew, that's pretty clever. I think ultimately we will have to use a standard NamedTuple type (ala #16580) for this. |
So is the idea to have a fully baked NamedTuple first and then implement this using that? Or make this change 1st w/ NamedTuple at some future date? |
This seems like a good change to me, and while some details are up in the air the important thing is the API change (namely, rest keywords being dict-like and immutable). Haven't run all tests yet, but this went pretty smoothly so far.
I think immutability really makes sense here since there tend to be few keyword args, and function arguments tend to be used in an immutable way. Positional varargs are of course already immutable. This already eliminates some allocations (unnecessary empty
Vector{Any}
s), and at least for small argument counts I expect this to speed up the hard-to-optimize uses of keyword args.I'm not sure what type to use here but
ImmutableDict{Symbol,Any}
seems to work well for now.Previously, rest keywords were sloppy about duplicates:
With this change, we use the constructed dict to de-duplicate the keyword names (keeping only the last one):
However, this is potentially costly since
ImmutableDict
lookup is O(n).At the same time, rest keywords need to preserve the order they were passed in, and
ImmutableDict
is perfect for that since it happens to be ordered. I know I've written code that assumes keyword arg order is preserved, but I guess we can consider dropping that guarantee.