Allowing zero-dimensional subscripts

Carl Banks invalidemail at aerojockey.com
Fri Jun 9 05:22:27 EDT 2006


Steve Holden wrote:
> Hey, I have an idea, why don't we look at the language reference manual
> instead of imagining how we think it might work!

I don't know.  Sounds risky.


> In section 3.2 we find:
>
>
> """
> Tuples
> The items of a tuple are arbitrary Python objects. Tuples of two or more
> items are formed by comma-separated lists of expressions. A tuple of one
> item (a `singleton') can be formed by affixing a comma to an expression
> (an expression by itself does not create a tuple, since parentheses must
> be usable for grouping of expressions). An empty tuple can be formed by
> an empty pair of parentheses.
> """
>
> So it seems that your speculation is false. Section 2.6 specifically
> defines "[" and "]" as delimiters. Section 5.3.2 defines a subscription
> (a term I've not really grown to love, but what the heck) as
>
> subscription ::= primary "[" expression_list "]"
>
> and section 5.12, which defines expression_list, explicitly says
>
> """An expression list containing at least one comma yields a tuple.""".
>
> So it would appear that while your change might be very convenient to
> allow you to refer to scalar values as zero-dimensional arrays, it
> doesn't really fit into Python's conceptual framework. Sorry.

Yes, that would appear to be so.  You would have a point... if the
documentation were correct.  Only it's not.

According to the reference manual, the rule for an expression_list is:

expression_list ::= expression ( "," expression )* [","]

But take the following legal Python subscripted array:

a[1:2,...,3:4]

Is "1:2" an expression?  How about "..."?  When I enter 1:2 at the
Python prompt, I get a syntax error.  The fact is, the documentation
here is either wrong or simplified or both.  (I don't think it's a big
deal, actually: the real grammar has lots of complexity to handle
tricky cases that would needlessly complicate the reference manual for
a human reader.)  So let's look at an excerpt the actual Python grammar
(from 2.4.3).  You'll be happy to know subscription isn't used. :)

trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
sliceop: ':' [test]
subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
testlist: test (',' test)* [',']

Clearly, the grammar rule used for list subscript is different from the
one used for list of expressions (for some reason, what an ordinary
person would call an expression is called a "test" in the grammar,
whereas "expr" is a non-short-circuiting expression).

So there's a regular way to create non-empty tuples, and a subscript
way.

And there's a regular way to create an empty tuple... but not a
subscript way.

So I'd say this change fits the conceptual framework of the tuple quite
well; in fact, it makes subscript tuples more parallel to their regular
counterparts.


> One further point: if you really do conceptualize scalars as
> zero-dimensional arrays, where is the value conceptually stored?

Think of it this way: an array with n-dimensions of length 3 would have
3**n total entries.  How many entries would a 0-dimensional array have?
 3**0 == 1.

Numeric has had zero-dimensional arrays for a long time, and has had no
problem storing them.  Think of the rule for accessing an element of an
array: it's a base pointer + sum (indices*stride) for all indices.  Now
generalize it down to zero: there are no indices, so the scalar is
stored at the base pointer.


Carl Banks




More information about the Python-list mailing list