# [Numpy-discussion] s are mutable scalars

Travis Oliphant oliphant at ee.byu.edu
Tue Sep 17 09:10:05 CDT 2002

```>
> Some of the choices between rank-0 arrays and new scalar types
> might be resolved by enumerating the properties desired of them.
>

> Most properties of rank-0 arrays could be fixed by consistency
> requirements alone, using operations that reduce array dimensions.
>
> Let a = ones((2,3,4))
> b = sum(a)
> c = sum(b)
> d = sum(c)
>
> Property 1: the shape of an array is a tuple of integers
> 	a.shape == (2, 3, 4)
> 	b.shape == (3, 4)
> 	c.shape == (4,)
> 	d.shape == ()
>
> Property 2: rank(a) == len(a.shape)
> 	rank(a) == 3 == len(a.shape)
> 	rank(b) == 2 == len(b.shape)
> 	rank(c) == 1 == len(c.shape)
> 	rank(d) == 0 == len(d.shape)
>
> Property 3: len(a) == a.shape[0]
> 	len(a) == 2 == a.shape[0]
> 	len(b) == 3 == b.shape[0]
> 	len(c) == 4 == c.shape[0]
> 	len(d) == Exception == d.shape[0]
>
> 	# Currently the last is wrong?

Agreed, but this is because d is an integer and out of Numerics control.
This is a case for returning 0d arrays rather than Python scalars.

>
> Property 4: size(a) == product(a.shape)
> 	size(a) == 24 == product(a.shape)
> 	size(b) == 12 == product(b.shape)
> 	size(c) == 4 == product(c.shape)
> 	size(d) == 1 == product(d.shape)
>
> 	# Currently the last is wrong

I disagree that this is wrong.  This works as described for me.

>
> Property 5: rank-0 array behaves as mutable numbers when used as value
> 	array(2)  is similar to 2
> 	array(2.0)  is similar to 2.0
> 	array(2j)  is similar to 2j
>
> 	# This is a summary of many concrete properties.
>
> Property 6: Indexing reduces rank. Slicing preserves rank.
> 	a[:,:,:].shape = (2, 3, 4)
> 	a[1,:,:].shape = (3, 4)
> 	a[1,1,:].shape = (4,)
> 	a[1,1,1].shape = ()
>
> Property 7: Indexing by tuple of ints gives scalar.
> 	a[1,1,1] == 1
> 	b[1,1] == 2
> 	c[1,] == 6
> 	d[()] == 24
>
> 	# So rank-0 array indexed by empty tuple should be scalar.
>         # Currently the last is wrong

>
> Property 8: Indexing by tuple of slices gives array.
> 	a[:,:,:] == ones((2,3,4))
> 	b[:,:] == ones((3,4)) * 2
> 	c[:] == ones((,4)) * 6
> 	d[()] == ones(()) * 24
>
> 	# So rank-0 array indexed by empty tuple should be rank-0 array.
>         # Currently the last is wrong

>
> Property 9: Indexing as lvalues
> 	a[1,1,1] = 2
> 	b[1,1] = 2
> 	c[1,] = 2
> 	d[()] = 2
>
> Property 10: Indexing and slicing as lvalues
> 	a[:,:,:] = ones((2, 3, 4))
> 	a[1,:,:] = ones((3, 4))
> 	a[1,1,:] = ones((4,))
> 	a[1,1,1] = ones(())
>
> 	# But the last is wrong.
>
>
> Conclusion 1: rank-0 arrays are equivalent to scalars.
> 	See properties 7 and 8.
>
> Conclusion 2: rank-0 arrays are mutable.
> 	See property 9.
>
> Conclusion 3: shape(scalar), size(scalar) are all defined, but len(scalar)
> 	should not be defined.

Why is this?  I thought you argued the other way for len(scalar).  Of
course, one solution is that we could overwrite the len() function and
allow it to work for scalars.

>
> 	See conclusion 1 and properties 1, 2, 3, 4.
>
> Conclusion 4: A missing axis is similar to having dimension 1.
> 	See property 4.
>
> Conclusion 5: rank-0 int arrays should be allowed to act as indices.
> 	See property 5.

Can't do this for lists and other builtin sequences.
>
> Conclusion 6: rank-0 arrays should not be hashable except by object id.
> 	See conclusion 2.
>
>
> Discussions:
>
>   - These properties correspond to the current implementation quite well,
> 	except a few rough edges.
>
>   - Mutable scalars are useful in their own rights.
>
>   - Is there substantial difference in overhead between rank-0 arrays and
>     scalars?

Yes.

>
>   - How to write literal values?  array(1) is too many characters.
>
>   - For rank-1 and rank-0 arrays, Python notation distinguishes:
>
> 	c[1] vs c[1,]
> 	d[] vs d[()]
>
>     Should these be used to handle semantic difference between indexing
>     and slicing?  Should d[] be syntactically allowed?
>
> Hope these observations help.

Thanks for the observations.

-Travis O.

```