Infix application of binary functions

It could help readability if binary (arity of 2) functions could be applied infix with some syntax. For example, borrowing from Haskell, the backtick could be reintroduced for this purpose. Good examples for this are isinstance and hasattr: if some_object `isinstance` Iterable: ... elif some_object `hasattr` '__iter__': ... It is already possible[1] to make infix functions, but the solution is a hack and requires functions to be marked as infix. (The use of backticks is just an example borrowing from Haskell and might not be optimal, although a benefit is that it isn't very noisy.) [1] http://code.activestate.com/recipes/384122-infix-operators/

On Wed, Jul 21, 2010 at 3:37 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote:
Already proposed (by me) and rejected by the BDFL: http://mail.python.org/pipermail/python-ideas/2007-January/000054.html Cheers, Chris -- http://blog.rebertia.com

Then what about: obj $isinstance Iterable or obj $isinstance$ Iterable or obj *isinstance Iterable or obj isinstance? Iterable These don't use the backtick charackter (wich on some setups even is a unicode char not from 7bit ascii). -panzi On 07/22/2010 01:17 AM, Chris Rebert wrote:

How would the parser distinguish that from multiplication?
or obj isinstance? Iterable
That would look odd for non-interoggative binary functions: z = x cartesianProduct? y
These don't use the backtick charackter (wich on some setups even is a unicode char not from 7bit ascii).
Not using backtick definitely makes the proposal more viable. (Personally I <3 backtick though.) Cheers, Chris

tor 2010-07-22 klockan 01:33 +0200 skrev Mathias Panzenböck:
I like the question mark, although it is only useful for predicates. I haven't considered if infix is useful for anything other than predicates, though. Another possibility is a keyword, maybe "of": obj isinstance of Iterable or obj hasattr of '__iter__' But better then would be a keyword that already exists and makes sense for this use. A character such as the question mark is probably best, just noting the possibility of a keyword for completeness sake. An example of a non-predicate infix might be str.format: 'Hello {}' str.format? 'World' Here, the question mark makes less sense.

Thought about it some more. Here’s a more general formula: class InfixArity(object): def __init__(self, arity): self.arity = arity self.args = [] def __call__(self, func): self.func = func return self def __add__(self, arg): self.args.append(arg) if len(self.args) < self.arity: return self else: return self.func(*self.args) __radd__ = __add__ Infix = lambda func: InfixArity(2)(func) And of course, one can use __mul__ or __div__ or whatever to taste. "1 // add // 2” doesn’t make me instantly vomit in my mouth. ;-) -- Carl Johnson

Last time, I swear! I caught a bug in the last version. Since I mutated my instances (not very Haskell-like!!), you couldn’t use the same function more than once. Here’s a new version that lets you use the same function again: class InfixArity(object): def __init__(self, arity): self.arity = arity def __call__(self, func): self.func = func return self def __add__(self, arg): return InfixHelper(self.func, self.arity, arg) __radd__ = __add__ __floordiv__ = __rfloordiv__ = __add__ __truediv__ = __rtruediv__ = __add__ class InfixHelper(object): def __init__(self, func, arity, firstarg): self.func = func self.arity = arity self.args = [firstarg] def __add__(self, arg): self.args.append(arg) if len(self.args) < self.arity: return self else: return self.func(*self.args) __radd__ = __add__ __floordiv__ = __rfloordiv__ = __add__ __truediv__ = __rtruediv__ = __add__ Infix = lambda func: InfixArity(2)(func) I imagine it would be possible to make an n-arity class that could work like “average // 1 // 2 // 3 // 4 // done” or maybe one that has you use a different operator for the last argument, but I leave that as an exercise for the reader. -- Carl Johnson On Wed, Jul 21, 2010 at 5:49 PM, Carl M. Johnson <cmjohnson.mailinglist@gmail.com> wrote:

This can be done in Python today:
Quoting myself from the original post: It is already possible[1] to make infix functions, but the solution is a hack and requires functions to be marked as infix. [1] http://code.activestate.com/recipes/384122-infix-operators/

Dag Odenhall <dag.odenhall@gmail.com> writes:
I don't see how “add a new punctuation character to the syntax in every place where this is to be used” is less of a hack. For reference you might want to read over the debates that preceded the introduction of ‘@’ to the language. There is *very strong* resistance to adding syntax that uses arbitrary punctuation characters. IMO that resistance is for good reason: punctuation beyond what Python already supports today rarely improves readability, and usually worsens it. -- \ “All television is educational television. The question is: | `\ what is it teaching?” —Nicholas Johnson | _o__) | Ben Finney

Already proposed (by me) and rejected by the BDFL:
http://mail.python.org/pipermail/python-ideas/2007-January/000054.html
Ah, thanks. He only rejects the backtick however, not infix application itself.

On Wed, Jul 21, 2010 at 3:37 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote:
Already proposed (by me) and rejected by the BDFL: http://mail.python.org/pipermail/python-ideas/2007-January/000054.html Cheers, Chris -- http://blog.rebertia.com

Then what about: obj $isinstance Iterable or obj $isinstance$ Iterable or obj *isinstance Iterable or obj isinstance? Iterable These don't use the backtick charackter (wich on some setups even is a unicode char not from 7bit ascii). -panzi On 07/22/2010 01:17 AM, Chris Rebert wrote:

How would the parser distinguish that from multiplication?
or obj isinstance? Iterable
That would look odd for non-interoggative binary functions: z = x cartesianProduct? y
These don't use the backtick charackter (wich on some setups even is a unicode char not from 7bit ascii).
Not using backtick definitely makes the proposal more viable. (Personally I <3 backtick though.) Cheers, Chris

tor 2010-07-22 klockan 01:33 +0200 skrev Mathias Panzenböck:
I like the question mark, although it is only useful for predicates. I haven't considered if infix is useful for anything other than predicates, though. Another possibility is a keyword, maybe "of": obj isinstance of Iterable or obj hasattr of '__iter__' But better then would be a keyword that already exists and makes sense for this use. A character such as the question mark is probably best, just noting the possibility of a keyword for completeness sake. An example of a non-predicate infix might be str.format: 'Hello {}' str.format? 'World' Here, the question mark makes less sense.

Thought about it some more. Here’s a more general formula: class InfixArity(object): def __init__(self, arity): self.arity = arity self.args = [] def __call__(self, func): self.func = func return self def __add__(self, arg): self.args.append(arg) if len(self.args) < self.arity: return self else: return self.func(*self.args) __radd__ = __add__ Infix = lambda func: InfixArity(2)(func) And of course, one can use __mul__ or __div__ or whatever to taste. "1 // add // 2” doesn’t make me instantly vomit in my mouth. ;-) -- Carl Johnson

Last time, I swear! I caught a bug in the last version. Since I mutated my instances (not very Haskell-like!!), you couldn’t use the same function more than once. Here’s a new version that lets you use the same function again: class InfixArity(object): def __init__(self, arity): self.arity = arity def __call__(self, func): self.func = func return self def __add__(self, arg): return InfixHelper(self.func, self.arity, arg) __radd__ = __add__ __floordiv__ = __rfloordiv__ = __add__ __truediv__ = __rtruediv__ = __add__ class InfixHelper(object): def __init__(self, func, arity, firstarg): self.func = func self.arity = arity self.args = [firstarg] def __add__(self, arg): self.args.append(arg) if len(self.args) < self.arity: return self else: return self.func(*self.args) __radd__ = __add__ __floordiv__ = __rfloordiv__ = __add__ __truediv__ = __rtruediv__ = __add__ Infix = lambda func: InfixArity(2)(func) I imagine it would be possible to make an n-arity class that could work like “average // 1 // 2 // 3 // 4 // done” or maybe one that has you use a different operator for the last argument, but I leave that as an exercise for the reader. -- Carl Johnson On Wed, Jul 21, 2010 at 5:49 PM, Carl M. Johnson <cmjohnson.mailinglist@gmail.com> wrote:

This can be done in Python today:
Quoting myself from the original post: It is already possible[1] to make infix functions, but the solution is a hack and requires functions to be marked as infix. [1] http://code.activestate.com/recipes/384122-infix-operators/

Dag Odenhall <dag.odenhall@gmail.com> writes:
I don't see how “add a new punctuation character to the syntax in every place where this is to be used” is less of a hack. For reference you might want to read over the debates that preceded the introduction of ‘@’ to the language. There is *very strong* resistance to adding syntax that uses arbitrary punctuation characters. IMO that resistance is for good reason: punctuation beyond what Python already supports today rarely improves readability, and usually worsens it. -- \ “All television is educational television. The question is: | `\ what is it teaching?” —Nicholas Johnson | _o__) | Ben Finney

Already proposed (by me) and rejected by the BDFL:
http://mail.python.org/pipermail/python-ideas/2007-January/000054.html
Ah, thanks. He only rejects the backtick however, not infix application itself.
participants (5)
-
Ben Finney
-
Carl M. Johnson
-
Chris Rebert
-
Dag Odenhall
-
Mathias Panzenböck