
On Jan 24, 2016, at 22:32, Terry Reedy <tjreedy@udel.edu> wrote:
A possibility would be to make {} a delayed and possibly partial call operator, in parallel to the current use of () as a immediate and total call operator. expr{arguments} would evaluate to a function, whether of type <function> or a special class similar to bound methods. The 'arguments' would be anything allowed within partial, which I believe is anything allowed in any function call. I chose {} because expr{...} is currently illegal, just as expr(arguments) is for anything other than a function call. On the other hand, expr[...] is currently legal, at least up to '[', as is expr<...> at least up to '<'.
I like the idea of "easy" partials, but I don't like this syntax. Many languages (Scala, C++ with boost::lambda, etc.) use a syntax something like this: hex = int(_, 16) binopen = open(_, "rb", *_, **_) setspam = setattr(spam, attr, _) The equivalent functions are: lambda x: int(x, 16) lambda arg, *args, **kw: open(arg, "rb", *args, **kw) lambda arg, *, _spam=spam, _attr=attr: setattr(_spam, _attr, arg) You can extend this to allow reordering arguments, similarly to the way %-formatting handles reordering: modexp = pow(_3, _1, _2) Obviously '_' only works if that's not a valid identifier (or if you're implementing things with horrible template metaprogramming tricks and argument-dependent lookup rather than in the language), but some other symbol like ':', '%', or '$' might work. I won't get into the ways you can extend this to expressions other than calls, like 2*_ or just (2*). The first problem with this syntax is that it doesn't give you a way to specify _all_ of the arguments and return a nullary partial. But you can always work around that with dummy params with default values. And it really doesn't come up that often in practice anyway in languages with this syntax, except in the special case that Python already handles with bound methods. The other big problem is that it just doesn't look like Python, no matter how much you squint. But going only half-way there, via an extended functools.partial that's more like boost bind than boost lambda isn't nearly as bad: hex = partial(int, _, 16) binopen = partial(open, _, "rb", *_, **_) setspam = partial(setattr, spam, attr, _) Only the last one can be built with partial today, and even that one seems a lot more comprehensible with the explicit ', _' showing that the resulting function takes one argument, and you can see exactly where that argument will go, than with the current implicit version. At any rate, I'm not sure I like either of these, but I definitely like them both better than: setspam = setattr{spam, attr}