>The question is, how would you _specify_ that option?

This seems like the perfect use case for function annotations, or a decorator. I imagine both cases would look rather pretty

def func(**kwargs: ordered):

def func(**kwargs):

I'm not sure if this is a bad idea for other reasons (e.g. decorators/annotations being reserved for library code rather than core language features) but it does look right intuitively: you are annotating the function or the kwarg to change it's behavior.

Here's another thought: macros would be able to pretty trivially give you a syntax like:

>>> odict(a = 1, b = 2)
OrderedDict([('a', 1), ('b', 2)])
>>> odict(b = 2, a = 1)
OrderedDict([('b', 2), ('a', 1)])


>>> o%dict(a = 1, b = 2)
OrderedDict([('a', 1), ('b', 2)])
>>> o%dict(b = 1, a = 1)
OrderedDict([('b', 2), ('a', 1)])

for ordered dict literals. It wouldn't work for generally adding orderliness to other functions, since the macro won't know which bindings are named arguments and which bindings are **kwargs, but it also looks really pretty. Probably not something you'd want to put in the std lib, but it's fun if you want to try out the syntax in your own projects.


On Tue, May 21, 2013 at 12:40 PM, Andrew Barnert <abarnert@yahoo.com> wrote:
On May 18, 2013, at 19:13, Haoyi Li <haoyi.sg@gmail.com> wrote:

Forgive me if this has been mentioned before (i don't think it has) but how about an option somehow to take the list of **kwargs as an association-list?

The question is, how would you _specify_ that option?

The best way I can think of is a function attribute, with a decorator to set the attribute. Similar to my earlier suggestion for a function attribute that takes a constructor callable.

Your idea is simpler conceptually, but it's not much simpler to use, and it's actually more complicated in implementation. 

The existing function calling machinery explicitly uses mapping functionality, at least in CPython and PyPy. Not that it would be _hard_ to rewrite it around a sequence instead, but it would still be harder than not doing so.

I am approaching this from a point of view of "why am I putting everything into a hashmap just to iterate over it later", as you can see in the way the namedtuple constructor is implemented:

This may be rather out-there, and I'm not sure if it'll speed things up much, but I'm guessing iterating over an assoc list is faster than iterating over anything else. Building an assoc list is also probably faster than building anything else and it's also the most easily convertible (either to OrderedDict or unordered dict) since it preserves all information.

But you're forgetting that the all existing kwargs code would get slower if we first built a list of pairs and then constructed a dict from it, as would any new code that wants to do lookup by name. So, you're slowing down the 90% case to speed up the 10% case.

Also, the existing functionality is something like this pseudocode:

    kwargs = dict(starstarargs)
    for arg, val in zip(namedargs, namedvals):
        if arg not in f.paramnames:
            kwargs[arg] = val

(I linked to the actual CPython and PyPy code earlier in the thread.)

So, if performance actually matters, presumably you're going to hash the names anyway to do that in check, at which point the biggest cost of using a dict is already incurred.