Thanks for the comments!
On 4/26/07, Travis E. Oliphant oliphant.travis@ieee.org wrote:
Forgive my ignorance, but I'm not really sure what this PEP is trying to do. I don't want to sound negative, I really just don't understand the purpose. I've just never encountered a problem this that I can see how this PEP will help me solve.
It's trying to do the same thing for numbers as Guido is doing for collections in PEP 3119: let people make the useful distinctions between them for whatever purposes people need to make distinctions. It looks like the community is a lot more comfortable with overloading than static typing, so some of the distinctions I proposed are probably too fine.
That doesn't mean it's not worthwhile, I just don't understand it.
Abstract
This proposal defines a hierarchy of Abstract Base Classes (ABCs) [#pep3119] to represent numbers and other algebraic entities similar to numbers. It proposes:
- A hierarchy of algebraic concepts, including monoids, groups, rings, and fields with successively more operators and constraints on their operators. This will be added as a new library module named "algebra".
The SAGE people may be interested in this, but I doubt there will more than a handful of users of these algebraic base classes.
I expected that if someone overloads a function between integers and rationals, the numeric people would be happier if the integer overload triggered for square matrices as well, in which case we'd want to encourage people to overload on Ring vs Field instead of Integral vs FractionalReal. You'd know better whether that's actually true. If not, I guess I'd better stop claiming that they'll be useful for the numpy people. :)
- A hierarchy of specifically numeric types, which can be converted to and from the native Python types. This will be added as a new library module named "numbers".
I could see having a hierarchy of "numbers" we have one in NumPy. All the NumPy array scalars fall under a hierarchy of types so that it is easy to check whether or not you have signed or unsigned integers, or inexact numbers.
Object oriented systems have a general problem in constraining functions that take two arguments. To take addition as an example, ``int(3) + int(4)`` is defined, and ``vector(1,2,3) + vector(3,4,5)`` is defined, but ``int(3) + vector(3,4,5)`` doesn't make much sense.
In NumPy, this kind of operation makes sense we just broadcast int(3) to the equivalent vector(3,3,3) and do the element-by-element operation.
This is how most array packages outside of Python do it as well.
Oops; I found a bad example. Does vector(3,3,3) + matrix([4,5],[6,7]) work? Are there other good examples of the addition having to be from the "same" group?
I think adding the abstract base-classes for "algebras" is more complicated than has been discussed if you are going to start treating arrays as elements in their own algebra. There is a lot of flexibility in how arrays can be viewed in an algebraic context.
Really? Since the operators work element-wise, I would think that a numpy array would have exactly the same algebraic structure as its elements. One could wrap an array to put it into a particular algebraic context, but the array itself seems pretty simple.
The author gives a valiant go at defining base classes for generic algebras, but I didn't see everything I've encountered in my travels through algebra, and I don't understand the motivation for trying to include these things in Python specifically.
Therefore, I would stick with defining a hierarchy of numbers and leave it at that for now (if I even went that far).
For numbers, several suggestions have been offered. In NumPy we use abstract base classes that look like this
Number Integer SignedInteger UnsignedInteger Inexact Floating ComplexFloating
But, this is because the array scalars in NumPy are based on C-data-types and not on general-purpose integers or floats. In NumPy it is useful to check if you have an integer-typed array and so the base-classes become useful.
Do you have an example of when you'd want to check for an integer-typed array?
At one point, Guido was asking for reasons to include Cardinal (aka Natural, aka Unsigned) in the hierarchy. Is UnsignedInteger only present in NumPy because it describes some native C types, or does it have some other purpose?
For general purpose Python, I would do something like
Complex Rational_Complex Integer_Complex Floating_Complex # uses hardware float Decimal_Complex Real Rational Integer Floating # uses hardware float Decimal
Are you specifying an abstract Floating type to incorporate both floats and doubles? Glancing over the Decimal spec, and trying a few things with the implementation, it looks like Decimal objects have a specific precision for each thread, which can be changed for future operations at any time. Is there still a reason to separate Floating and Decimal, or will a modification of FloatingReal suffice?
Thanks again, Jeffrey