Ordering Products

Kay Schluehr kay.schluehr at gmx.net
Tue Jul 19 02:54:42 EDT 2005


Diez B.Roggisch wrote:
> > I have to admit that I don't understand what you mean with the
> > 'constant parts' of an expression?
>
> >From what I percieved of your example it seemed to me that you wanted to
> evaluate the constants like 7*9 first, so that an expression like
>
> a * 7 * 9 * b
>
> with variables a,b is evaluated like this:
>
> a * 63 * b
>
> So my suggestion was simply to make the *-operator more precedent when
> in between two constants. What I mean with constants here are  of course
> integer/float literals. The concept of a differing operator precedence
> can be extended to arbitray elements when their types are known - which
> should be possible when variable values are known at parsing
> time.

O.K.

>
> > The associativity of __mul__ is trivially fullfilled for the dummy
> > class M if an additional __eq__ method is defined by comparing factor
> > lists because those lists are always flat:
>
> I don't care about that, as my approach deosn't use python's built-in parser
>  - it can't, as that wouldn't allow to re-define operator  precedence.

Diez, I try not to care too much about global operator precedence of
builtin infix operators. The hard problems in designing a CAS beyond
Mathematica are related to a bunch of interoperating algebras all
defining their own operations. Finally only local precedences exist
that are characteristic for certain patterns of expressions with a lot
of tangled operators ( e.g. 'geometric algebra' with vector products,
wedge products, inner products, additions and subtractions ). I don't
want a system defining a syntactically extendable language with 10
custom punctuations per module that no one ( at least not me ) can
remind and which looks as awkward as regular expressions.


> What you do is to
> simply collect the factors as list. But what you need (IMHO) is a parsing
> tree (AST) that reflects your desired behaviour by introducing a different
> precedence thus that the expression
>
> a * 7 *9 * b
>
> is not evaluated like
>
> ((a*7)*9)*b
>
> (which is a tree, and the standard way of evaluationg due to built-in parsers
> precedence rules) but as
>
> a*(7*9)*b
>
> which is also a tree.

Yes, but I tend to use __mul__ just for convenience. It is reflecting
an associative and non-commutative operator whereas __add__ is a
convenient way to fix an associative and commutative operator. In an
idealized mathematical interpretation they represent nothing specific
but as language elements they shall be fixed somehow.

For more general operations one may define functional operators e.g.
r_assoc and l_assoc where following (in)equations hold:

l_assoc(a,b,c) == l_assoc(l_assoc(a,b),c)
l_assoc(a,b,c) != l_assoc(a, l_assoc(b,c))

r_assoc(a,b,c) == r_assoc(a,r_assoc(b,c))
r_assoc(a,b,c) != r_assoc(r_assoc(a,b),c)

This kind of pattern can be used to define rules about l_assoc and
r_assoc.

Nevertheless, there is no loss of generality. The system lacks
prevention from deriving some class providing __mul__ and overwrite the
implementation of __mul__ using l_assoc. People may do this on their
own risk. 

Kay




More information about the Python-list mailing list