# [Numpy-discussion] Array scalar math ideas

Colin J. Williams cjw at sympatico.ca
Fri Mar 17 14:35:03 CST 2006

```Sasha wrote:

>On 3/16/06, Colin J. Williams <cjw at sympatico.ca> wrote:
>
>
>>Would it make sense to reconsider the costs and benefits of dealing with
>>dimensionless arrays?
>>
>>
>
>http://projects.scipy.org/scipy/numpy/wiki/ZeroRankArray
>
>http://aspn.activestate.com/ASPN/Mail/Message/2499954
>
>http://aspn.activestate.com/ASPN/Mail/Message/numpy-discussion/3028210
>
>This horse has suffered a lot beating ...
>
>
>
Sasha,

Many thanks, this sets things out clearly.  On a first scan, one thing
caught my eye:

I think we should implement Python scalars for the other types and then
eliminate rank-0 arrays completely. I could have a student do this in a
few weeks if it was agreed on.

-Travis Oliphant [13-Sep-02]

The Wiki sems to start with the design decision to implement zero
dimension arrays.
It then goes on to explore the problems created by that design decision.

My contribution to the second thread you quote was:

It looks as though a decision has been made.  I was among those who
favoured abandoning rank-0 arrays, we lost.

To my mind rank-0 arrays add complexity for little benefit and make
explanation more difficult.

I don"t spot any discussion in the PEP of the pros and cons of the nd ==
0 case.

Colin W. [20-Mar-05]

Ralf Juengling responded:

A correction!
There is, in the PEP::

Questions

1) should sequence behavior (i.e. some combination of slicing,
indexing, and len) be supported for 0-dim arrays?

Pros:  It means that len(a) always works and returns the size
of the array.  Slicing code and indexing code
will work for any dimension (the 0-dim array is an
identity element for the operation of slicing)

Cons:  0-dim arrays are really scalars.  They should behave
like Python scalars which do not allow sequence behavior

2) should array operations that result in a 0-dim array that
is the same basic type as one of the Python scalars, return the

Pros:

1) Some cases when Python expects an integer (the most
dramatic is when slicing and indexing a sequence:
_PyEval_SliceIndex in ceval.c) it will not try to
convert it to an integer first before raising an error.
Therefore it is convenient to have 0-dim arrays that
are integers converted for you by the array object.

2) No risk of user confusion by having two types that
are nearly but not exactly the same and whose separate
existence can only be explained by the history of
Python and NumPy development.

3) No problems with code that does explicit typechecks
(isinstance(x, float) or type(x) ==
types.FloatType). Although explicit typechecks are
considered bad practice in general, there are a couple
of valid reasons to use them.

4) No creation of a dependency on Numeric in pickle
files (though this could also be done by a special case
in the pickling code for arrays)

Cons:  It is difficult to write generic code because scalars
do not have the same methods and attributes as arrays.
(such as .type  or .shape).  Also Python scalars have
different numeric behavior as well.

This results in a special-case checking that is not
pleasant.  Fundamentally it lets the user believe that
somehow multidimensional homoegeneous arrays
are something like Python lists (which except for
Object arrays they are not).

For me and for the end user, the (2) Pros win.

I agree.  Incidentally, the 0-d discussion does not appear in the
12-Jan-06 version of the PEP.

I don't fully understand your proposal of 18-Feb-06 although I support
Francesc's suggestion that we avoid "rank" to mean the number of dimensions.

For matrices, we accept the rule that a matrix has two dimensions, not more
not less.  What problems would be created if we had the rule that an array
has not less than one dimension?

The little script below produces different results, depending on the ordering
of the operands.  This provides another challenge for the newcomer.

Colin W.

# arrayStuff.py

def inArrayWorld():
import numpy as _n
a= _n.arange(4)
return a[2]

def anotherWorld(a):
import math
w= 2.6 * a
x= a * 2
y= 2.6 * a
z= math.log10(a)
return z, type(z), type(y), type(x), type(w)

print anotherWorld(inArrayWorld())

```