Well, I finally ran into a Python Unicode problem, sort of

BartC bc at freeuk.com
Mon Jul 4 06:05:03 EDT 2016


On 04/07/2016 03:30, Steven D'Aprano wrote:
> On Mon, 4 Jul 2016 10:17 am, BartC wrote:
>
>> On 04/07/2016 01:00, Lawrence D’Oliveiro wrote:
>>> On Monday, July 4, 2016 at 11:47:26 AM UTC+12, eryk sun wrote:
>>>> Python lacks a mechanism to add user-defined operators. (R has this
>>>> capability.) Maybe this feature could be added.
>>>
>>> That would be neat. But remember, you would have to define the operator
>>> precedence as well. So you could no longer use a recursive-descent
>>> parser.
>>
>> That wouldn't be a problem provided the new operator symbol and its
>> precedence is known at a compile time, and defined before use.
>
> You're still having problems with the whole Python-as-a-dynamic-language
> thing, aren't you? :-)

Well it isn't completely dynamic, not unless code only exists as a eval 
or exec argument string (and even there, any changes will only be seen 
on calling eval or exec again on the same string).

Most Pythons seem to pre-compile code before executing the result. That 
pre-compilation requires that operators and precedences are known in 
advance and the resulting instructions are then hard-coded before execution.

> In full generality, you would want to be able to define unary prefix, unary
> suffix and binary infix operators, and set their precedence and whether
> they associate to the left or the right. That's probably a bit much to
> expect.

No, that's all possible. Maybe that's even how some language 
implementations work, defining all the set of standard operators at the 
start.

> But if we limit ourselves to the boring case of binary infix operators of a
> single precedence and associtivity, there's a simple approach: the parser
> can allow any unicode code point of category "Sm" as a legal operator, e.g.
> x ∇ y. Pre-defined operators like + - * etc continue to call the same
> dunder methods they already do, but anything else tries calling:
>
> x.__oper__('∇', y)
> y.__roper__('∇', x)
>
> and if neither of those exist and return a result other than NotImplemented,
> then finally raise a runtime TypeError('undefined operator ∇').

A simpler approach is to treat user-defined operators as aliases for 
functions:

def myadd(a,b):
	return a+b

operator ∇:
    (myadd,2,+3)   # map to myadd, 2 operands, prio 3, LTR

x = y ∇ z

is then equivalent to:

x = myadd(y,z)

However you will usually want to be able overload the same operator for 
different operand types. That means mapping the operator to one of 
several methods. Maybe even allowing the operator to have either one or 
two operands.

Trickier but still doable I think.

-- 
Bartc



More information about the Python-list mailing list