Allowing zero-dimensional subscripts

Steve Holden steve at holdenweb.com
Fri Jun 9 06:06:12 EDT 2006


Carl Banks wrote:
> 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]
> 
But the element inside the brackets there isn't  an expression-list, 
it's a slicing (see section 5.3.2).

> Is "1:2" an expression?  How about "..."?  When I enter 1:2 at the

1:2 is a short slice.

... is an ellipsis.

Neither of these elements are allowed in non-subscripting contexts.

> 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)* [',']
> 
The simplification of the grammar is explicitly documented:

"""
Rather than further complicating the syntax, this is disambiguated by 
defining that in this case the interpretation as a subscription takes 
priority over the interpretation as a slicing (this is the case if the 
slice list contains no proper slice nor ellipses). Similarly, when the 
slice list has exactly one short slice and no trailing comma, the 
interpretation as a simple slicing takes priority over that as an 
extended slicing.
"""

> 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.
> 
Although this debate is beginning to make me sound like one, I am really 
not a language lawyer. However, I should point out that what you are 
describing as a "tuple" should more correctly be described as a 
"slice-list" once you include slices or an ellipsis as elements. 
Slicings are described, as I am fairly sure you know, in section 5.3.3.
> 
>>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.
> 
I can see that, and it doesn't seem unreasonable. Fortunately your 
persistence has goaded me into determining the point that *did* seem 
unreasonable to me: you were falsely trying to equate slicings and tuples.

Having said all of which, there probably *is* a case for proposing that 
an empty slicing become syntactically acceptable, so why not write the 
PEP and go for it?

But be quick: feature freeze for 2.5b1 looms ...

regards
  Steve
-- 
Steve Holden       +44 150 684 7255  +1 800 494 3119
Holden Web LLC/Ltd          http://www.holdenweb.com
Love me, love my blog  http://holdenweb.blogspot.com
Recent Ramblings     http://del.icio.us/steve.holden




More information about the Python-list mailing list