[PEP draft 2] Adding new math operators

Huaiyu Zhu hzhu at localhost.localdomain
Wed Aug 9 20:16:16 EDT 2000


On Wed, 09 Aug 2000 23:01:45 GMT, Tim Hochberg <tim.hochberg at ieee.org> wrote:
>
>def elementandmatrixwise_multiply2(a, b, c):
>   a, b, c = asarray(a, Float), asarray(b, Float), asarray(c, Float)
>   return (a.M*b.M) * c

What if this happens in the middle of code?  Like

x = vector from matrix computaion
y = vector from matrix computaion
z = x ~+ y.T  # generating a 2d array for plotting
mesh(z)

Presumably it would be
z = asarray(x) + asarray(y.T)

It appears that this just admits that conversion by method call like .E is
not generally feasible given Python's current type/class dichotomy. Or you
have to assume anywhere you want this it's not going to be a scalar.

>Yes, but if you have calls from outside the module all bets are off. I
>suppose it would be OK to assume all objects are of a given type in a
>function if that function is only called from within the module, but
>modules that are called from outside should generally have their
>arguments checked and adjusted. However, given that you know what the
>input types are going to be inside a module, the differences between
>the .E and the ~* notation only come up in the scalar case discussed
>above.

No, they come up whenver you want to do a different type of operation, and
you have to decide whether you're going to leave the result in current
flavor or cast it back to what's prevalent surrounding it (while you don't
have enough information to decide).

>The ~* notation does appear to have an advantage in this
>case. For me, the advantages of checking things at the module
>boundaries outweigh the extra line that's required, so I don't see
>this as a big problem.

The issue at module or function boundaries is not important compared with
what's inside (and what they return).  You might have to do things like

x = asarray(f(a)) +  asarray(f(b))  asarray(f(c))

because f happens to return the wrong flavor.  And if f can return numbers
you can't use the f(a).E notation.

>
>In addition I still really don't like the fact that ~* and * could mean
>opposite things depending on whether an object was an array or a
>matrix. While this may rarely be a problem, when it is a problem it
>could be confusing and hard to track down.

This would be a problem only if objects change flavor frequently.  Given the
convenience of using ~op there's really no need to do that, at least no more
than what is already the case now between NumPy and MatPy interfaces. 

>> On the other hand, if the difference is in operands, you can't be sure the
>> flavor of the objects in any big chunk of code if both operations exist,
>> unless you set up a convention to always cast back to a given flavor after
>> each operation. That's what I think was the reason someone came up with the
>> "non-persistent-type" or "shadow" classes approach.  This is 40% of the
>> issue (IMO).
>
>I understand the urge for shadow type operands, but I think they
>introduce more problems than they solve. The rules for straightforward
>conversions are, well, straightforward. I suspect that shadow type
>operands would be either confusing, hard to implement fully, or
>both. I addition, I think that disallowing mixed type operations would
>catch the vast majority of the errors that could creep in through
>when forgetting to cast back and forth.

In a lot of places, the operands are of very similar types.  If you forget
to cast one of them, it's likely the you'll forget the other.  This is
especially so if they are returned by functions.

The shadow type does introduce a lot of additional problems, but it at least
ensures that you know the flavors of _all_ objects in a piece of code.  

>The test here is looking at code. People need to start coughing up
>real code that uses mixed type operations and start seeing whether
>real functions look like in both notations. The only matrix operation
>that I use with any regularity is dot, so mine would be pretty
>boring. Anyone have any good examples?

Well, this would only be possible if you could specify where to use
asarray(a) and a.E and so on.  That's the 55% of the issue. :-)

Huaiyu



More information about the Python-list mailing list