On 13 October 2012 16:22, Mike Meyer <mwm@mired.org> wrote:
On Sat, 13 Oct 2012 19:18:12 +1100
Steven D'Aprano <steve@pearwood.info> wrote:

> On 13/10/12 19:05, Yuval Greenfield wrote:
> I believe that Haskell treats operators as if they were function objects,
> so you could do something like:

For the record, Haskell allows operators to be used as functions by
quoting them in ()'s (to provide the functionality of operator) and to
turn functions into operators by quoting them in ``'s.

> negative_values = map(-, values)
>
> but I think that puts the emphasis on the wrong thing. If (and that's a big
> if) we did something like this, it should be a pair of methods __op__ and
> the right-hand version __rop__ which get called on the *operands*, not the
> operator/function object:
>
> def __op__(self, other, symbol)

Yeah, but then your function has to dispatch for *all*
operators. Depending on how we handle backwards compatibility with
__add__ et. al.

I'd rather slice it the other way (leveraging $ being unsused):

def __$<op>__(self, other, right):

so it only has to dispatch on left/right invocation.

<op> must match a new grammer symbol "operator_symbol", with limits on
it to for readability reasons: say at most three characters, all
coming from an appropriate unicode class or classes (you want to catch
the current operators and dollar sign).

Both of these leave both operator precedence and backwards
compatibility to be dealt with.

If anyone is taking this as more than a bit of fun, stop it.

How'er, for all you wanting something a bit more concrete to play with, I've got something that simulates infix based off something I'd found on the netz sometime who's author I do not remember.

The code is one Codepad for brevity, and it lets you do things like this:

 >>> (2 *dot* "__mul__" |mappedover| 10-to-25) >> tolist
[20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48]

Note that this is a contrived example equivalent to:

 >>> list(map((2).__mul__, range(10, 25)))
[20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48]

and mixing the styles you can get a quite nice:

 >>> map((2).__mul__, 10-to-25) >> tolist
[20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48] 

which would actually look readable if it was considered mainstream.

Note that making an in-line function is as simple as:

>>> @Inline
... def multiply(x, y): return x*y
... 
>>> 3 ^multiply^ 3
9

and that you can use any surrounding operators (other than comparisons)  to chose your operator priority or what reads well:

>>> 1 |div| 3 |div| 3
0.1111111111111111
>>> 1 |div| 3 *div* 3
1.0

and finally you also get "coercion" to functions á la Haskell:

>>> 2 |(div|3)
0.6666666666666666
>>> (div|3)(2)
0.6666666666666666

but I wouldn't even hope of calling it stable code or low on WTFs (if the above wasn't enough):

>>> (div|(div|3))(3) # Go on, guess why!
1.0
>>> 2 + (div|3) # 'Cause you can, yo
0.6666666666666666

These could both be "fixed" by making an infix require the same operator on both sides, which would make these both errors, but that wouldn't catch cases like (or*(div|3))(3) anyway.

So enjoy. Or not. Preferably not.