Allowing zero-dimensional subscripts

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • spam.noam@gmail.com

    #1

    Allowing zero-dimensional subscripts

    Hello,

    I discovered that I needed a small change to the Python grammar. I
    would like to hear what you think about it.

    In two lines:
    Currently, the expression "x[]" is a syntax error.
    I suggest that it will be evaluated like "x[()]", just as "x[a, b]" is
    evaluated like "x[(a, b)]" right now.

    In a few more words: Currently, an object can be subscripted by a few
    elements, separated by commas. It is evaluated as if the object was
    subscripted by a tuple containing those elements. I suggest that an
    object will also be subscriptable with no elements at all, and it will
    be evaluated as if the object was subscripted by an empty tuple.

    It involves no backwards incompatibiliti es, since we are dealing with
    the legalization of a currently illegal syntax.

    It is consistent with the current syntax. Consider that these
    identities currently hold:

    x[i, j, k] <--> x[(i, j, k)]
    x[i, j] <--> x[(i, j)]
    x[i, ] <--> x[(i, )]
    x[i] <--> x[(i)]

    I suggest that the next identity will hold too:

    x[] <--> x[()]

    I need this in order to be able to refer to zero-dimensional arrays
    nicely. In NumPy, you can have arrays with a different number of
    dimensions. In order to refer to a value in a two-dimensional array,
    you write a[i, j]. In order to refer to a value in a one-dimensional
    array, you write a[i]. You can also have a zero-dimensional array,
    which holds a single value (a scalar). To refer to its value, you
    currently need to write a[()], which is unexpected - the user may not
    even know that when he writes a[i, j] he constructs a tuple, so he
    won't guess the a[()] syntax. If my suggestion is accepted, he will be
    able to write a[] in order to refer to the value, as expected. It will
    even work without changing the NumPy package at all!

    In the normal use of NumPy, you usually don't encounter
    zero-dimensional arrays. However, I'm designing another library for
    managing multi-dimensional arrays of data. Its purpose is similiar to
    that of a spreadsheet - analyze data and preserve the relations between
    a source of a calculation and its destination. In such an environment
    you may have a lot of multi-dimensional arrays - for example, the sales
    of several products over several time periods. But you may also have a
    lot of zero-dimensional arrays, that is, single values - for example,
    the income tax. I want the access to the zero-dimensional arrays to be
    consistent with the access to the multi-dimensional arrays. Just using
    the name of the zero-dimensional array to obtain its value isn't going
    to work - the array and the value it contains have to be distinguished.

    I have tried to change CPython to support it, and it was fairly easy.
    You can see the diff against the current SVN here:

    The test suite passes without changes, as expected. I didn't include
    diffs of autogenerated files. I know almost nothing about the AST, so I
    would appreciate it if someone who is familiar with the AST will check
    to see if I did it right. It does seem to work, though.

    Well, what do you think about this?

    Have a good day,
    Noam Raphael

  • Terry Reedy

    #2
    Re: Allowing zero-dimensional subscripts


    <spam.noam@gmai l.com> wrote in message
    news:1149801040 .936452.26270@i 40g2000cwc.goog legroups.com...[color=blue]
    > Hello,
    >
    > I discovered that I needed a small change to the Python grammar. I
    > would like to hear what you think about it.
    >
    > In two lines:
    > Currently, the expression "x[]" is a syntax error.
    > I suggest that it will be evaluated like "x[()]", just as "x[a, b]" is
    > evaluated like "x[(a, b)]" right now.
    >
    > In a few more words: Currently, an object can be subscripted by a few
    > elements, separated by commas. It is evaluated as if the object was
    > subscripted by a tuple containing those elements.[/color]

    It is not 'as if'. 'a,b' *is* a tuple and the object *is* subcripted by a
    tuple.
    Adding () around the non-empty tuple adds nothing except a bit of noise.
    [color=blue][color=green][color=darkred]
    >>> dis(compile('x[a,b]','','eval'))[/color][/color][/color]
    0 0 LOAD_NAME 0 (x)
    3 LOAD_NAME 1 (a)
    6 LOAD_NAME 2 (b)
    9 BUILD_TUPLE 2
    12 BINARY_SUBSCR
    13 RETURN_VALUE[color=blue][color=green][color=darkred]
    >>> dis(compile('x[(a,b)]','','eval'))[/color][/color][/color]
    0 0 LOAD_NAME 0 (x)
    3 LOAD_NAME 1 (a)
    6 LOAD_NAME 2 (b)
    9 BUILD_TUPLE 2
    12 BINARY_SUBSCR
    13 RETURN_VALUE

    Parens around non-empty tuples are only needed for precedence grouping, the
    same as in (a+b)*c.
    [color=blue]
    >I suggest that an
    > object will also be subscriptable with no elements at all, and it will
    > be evaluated as if the object was subscripted by an empty tuple.[/color]

    Again, there would be no 'as if' about it. You are suggesting that the
    parens around a tuple nothing be optional in this particular context.
    While logically possible, Guido decided that tuple nothings should *always*
    be distinguished from other nothings and set off from surrounding code by
    parentheses. The reason is to avoid ambiguity and catch errors. I think
    this is overall a good choice.

    Terry Jan Reedy



    Comment

    • spam.noam@gmail.com

      #3
      Re: Allowing zero-dimensional subscripts

      Hello,

      Terry Reedy wrote:[color=blue][color=green]
      > > In a few more words: Currently, an object can be subscripted by a few
      > > elements, separated by commas. It is evaluated as if the object was
      > > subscripted by a tuple containing those elements.[/color]
      >
      > It is not 'as if'. 'a,b' *is* a tuple and the object *is* subcripted by a
      > tuple.
      > Adding () around the non-empty tuple adds nothing except a bit of noise.
      >[/color]

      It doesn't necessarily matter, but technically, it is not "a tuple".
      The "1, 2" in "x[1, 2]" isn't evaluated according to the same rules as
      in "x = 1, 2" - for example, you can have "x[1, 2:3:4, ..., 5]", which
      isn't a legal tuple outside of square braces - in fact, it even isn't
      legal inside parens: "x[(1, 2:3:4, ..., 5)]" isn't legal syntax.

      Noam

      Comment

      • Terry Reedy

        #4
        Re: Allowing zero-dimensional subscripts


        <spam.noam@gmai l.com> wrote in message
        news:1149807149 .516004.48590@f 6g2000cwb.googl egroups.com...[color=blue]
        > Terry Reedy wrote:[color=green][color=darkred]
        >> > In a few more words: Currently, an object can be subscripted by a few
        >> > elements, separated by commas. It is evaluated as if the object was
        >> > subscripted by a tuple containing those elements.[/color]
        >>
        >> It is not 'as if'. 'a,b' *is* a tuple and the object *is* subcripted
        >> by a
        >> tuple.
        >> Adding () around the non-empty tuple adds nothing except a bit of noise.
        >>[/color]
        >
        > It doesn't necessarily matter, but technically, it is not "a tuple".[/color]

        Tell that to the compiler. Here the code again.
        [color=blue][color=green][color=darkred]
        >>> dis(compile('x[a,b]','','eval'))[/color][/color][/color]
        0 0 LOAD_NAME 0 (x)
        3 LOAD_NAME 1 (a)
        6 LOAD_NAME 2 (b)
        9 BUILD_TUPLE 2
        12 BINARY_SUBSCR
        13 RETURN_VALUE[color=blue][color=green][color=darkred]
        >>> dis(compile('x= a,b','','single '))[/color][/color][/color]
        1 0 LOAD_NAME 0 (a)
        3 LOAD_NAME 1 (b)
        6 BUILD_TUPLE 2
        9 STORE_NAME 2 (x)
        12 LOAD_CONST 0 (None)
        15 RETURN_VALUE

        The same exact code to build the tuple a,b.
        [color=blue]
        > The "1, 2" in "x[1, 2]" isn't evaluated according to the same rules as
        > in "x = 1, 2"[/color]
        [color=blue][color=green][color=darkred]
        >>> dis(compile('x[1,2]','','eval'))[/color][/color][/color]
        0 0 LOAD_NAME 0 (x)
        3 LOAD_CONST 2 ((1, 2))
        6 BINARY_SUBSCR
        7 RETURN_VALUE[color=blue][color=green][color=darkred]
        >>> dis(compile('x= 1,2','','single '))[/color][/color][/color]
        1 0 LOAD_CONST 3 ((1, 2))
        3 STORE_NAME 0 (x)
        6 LOAD_CONST 2 (None)
        9 RETURN_VALUE

        Same exact tuple literal. The tuple rules are the same.
        [color=blue]
        >- for example, you can have "x[1, 2:3:4, ..., 5]", which
        > isn't a legal tuple outside of square braces - in fact, it even isn't
        > legal inside parens: "x[(1, 2:3:4, ..., 5)]" isn't legal syntax.[/color]

        Yes, slice and ellipsis literals are only valid directly inside brackets.
        And it is definitely worth knowing about them and that this is one place
        where a tuple cannot be parenthesized. But once they are accepted, the
        slice and ellipsis objects are members of the resulting tuple like any
        other.
        [color=blue][color=green][color=darkred]
        >>> dis(compile("x[1, 2:3:4, ..., 5]", '','eval'))[/color][/color][/color]
        0 0 LOAD_NAME 0 (x)
        3 LOAD_CONST 0 (1)
        6 LOAD_CONST 1 (2)
        9 LOAD_CONST 2 (3)
        12 LOAD_CONST 3 (4)
        15 BUILD_SLICE 3
        18 LOAD_CONST 4 (Ellipsis)
        21 LOAD_CONST 5 (5)
        24 BUILD_TUPLE 4
        27 BINARY_SUBSCR
        28 RETURN_VALUE

        So I do not see any point or usefulness in saying that a tuple subcript is
        not what it is.

        Terry Jan Reedy



        Comment

        • spam.noam@gmail.com

          #5
          Re: Allowing zero-dimensional subscripts

          Hello,

          Terry Reedy wrote:[color=blue]
          > So I do not see any point or usefulness in saying that a tuple subcript is
          > not what it is.[/color]

          I know that a tuple is *constructed*. The question is, is this,
          conceptually, the feature that allows you to ommit the parentheses of a
          tuple in some cases. If we see this as the same feature, it's
          reasonable that "nothing" won't be seen as an empty tuple, just like "a
          = " doesn't mean "a = ()".

          However, if we see this as a different feature, which allows
          multidimensiona l subscript by constructing a tuple behind the scenes,
          constructing an empty tuple for x[] seems very reasonable to me. Since
          in some cases you can't have the parentheses at all, I think that x[]
          makes sense.

          Noam

          Comment

          • Steve Holden

            #6
            Re: Allowing zero-dimensional subscripts

            spam.noam@gmail .com wrote:[color=blue]
            > Hello,
            >
            > Terry Reedy wrote:
            >[color=green]
            >>So I do not see any point or usefulness in saying that a tuple subcript is
            >>not what it is.[/color]
            >
            >
            > I know that a tuple is *constructed*. The question is, is this,
            > conceptually, the feature that allows you to ommit the parentheses of a
            > tuple in some cases. If we see this as the same feature, it's
            > reasonable that "nothing" won't be seen as an empty tuple, just like "a
            > = " doesn't mean "a = ()".
            >
            > However, if we see this as a different feature, which allows
            > multidimensiona l subscript by constructing a tuple behind the scenes,
            > constructing an empty tuple for x[] seems very reasonable to me. Since
            > in some cases you can't have the parentheses at all, I think that x[]
            > makes sense.
            >[/color]
            Hey, I have an idea, why don't we look at the language reference manual
            instead of imagining how we think it might work!

            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.

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

            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

            Comment

            • Fredrik Lundh

              #7
              Re: Allowing zero-dimensional subscripts

              spam.noam@gmail .com wrote:
              [color=blue]
              > Well, what do you think about this?[/color]

              -0 from me, but it's definitely a PEP-able proposal.

              suggestion: turn your post into a pre-PEP and post it somewhere, post
              the patch to the patch tracker, and post a brief heads-up to python-dev,
              and see what happens.

              (you probably have to do all that today if you want this to go into 2.5,
              though...)

              </F>

              Comment

              • Terry Reedy

                #8
                Re: Allowing zero-dimensional subscripts


                <spam.noam@gmai l.com> wrote in message
                news:1149832139 .948242.64160@f 6g2000cwb.googl egroups.com...[color=blue]
                > The question is, is this,
                > conceptually, the feature that allows you to ommit the parentheses of a
                > tuple in some cases.[/color]

                To repeat: tuples are defined by commas. There are no 'parentheses of a
                tuple', except for empty tuples, to be omitted. Consider: a+b is a sum; in
                (a+b)*c, the sum is parenthesized to avoid confusion with a+b*c. Like
                other expressions, tuples are parenthesezed when needed to avoid similar
                confusion. So (1,2)+(3,4) needs parens because 1,2+3,4 would be something
                different. In both examples, parens are used to reverse normal precedence
                relations.

                Terry Jan Reedy



                Comment

                • Carl Banks

                  #9
                  Re: Allowing zero-dimensional subscripts

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

                  I don't know. Sounds risky.

                  [color=blue]
                  > 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.[/color]

                  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.

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

                  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

                  Comment

                  • Steve Holden

                    #10
                    Re: Allowing zero-dimensional subscripts

                    Carl Banks wrote:[color=blue]
                    > Steve Holden wrote:
                    >[color=green]
                    >>Hey, I have an idea, why don't we look at the language reference manual
                    >>instead of imagining how we think it might work![/color]
                    >
                    >
                    > I don't know. Sounds risky.
                    >
                    >
                    >[color=green]
                    >>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
                    >>
                    >>subscriptio n ::= 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.[/color]
                    >
                    >
                    > 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]
                    >[/color]
                    But the element inside the brackets there isn't an expression-list,
                    it's a slicing (see section 5.3.2).
                    [color=blue]
                    > Is "1:2" an expression? How about "..."? When I enter 1:2 at the[/color]

                    1:2 is a short slice.

                    .... is an ellipsis.

                    Neither of these elements are allowed in non-subscripting contexts.
                    [color=blue]
                    > 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)* [',']
                    >[/color]
                    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.
                    """
                    [color=blue]
                    > 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.
                    >[/color]
                    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.[color=blue]
                    >[color=green]
                    >>One further point: if you really do conceptualize scalars as
                    >>zero-dimensional arrays, where is the value conceptually stored?[/color]
                    >
                    >
                    > 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.
                    >[/color]
                    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

                    Comment

                    • Fredrik Lundh

                      #11
                      Re: Allowing zero-dimensional subscripts

                      Sybren Stuvel wrote:
                      [color=blue]
                      > Just curious: how would you initialize 'x' in such a case? If I simply
                      > say 'x = []' and then try to index it with x[1, 2], I get "TypeError:
                      > list indices must be integers".[/color]

                      that's up to the x implementation to decide, of course:
                      [color=blue][color=green][color=darkred]
                      >>> class MyContainer:[/color][/color][/color]
                      .... def __getitem__(sel f, index):
                      .... return index
                      ....[color=blue][color=green][color=darkred]
                      >>> x = MyContainer()
                      >>> x[1][/color][/color][/color]
                      1[color=blue][color=green][color=darkred]
                      >>> x[1, 2][/color][/color][/color]
                      (1, 2)[color=blue][color=green][color=darkred]
                      >>> x[(1, 2, 3)][/color][/color][/color]
                      (1, 2, 3)[color=blue][color=green][color=darkred]
                      >>> x[()][/color][/color][/color]
                      ()

                      noam's proposal is to make this work:
                      [color=blue][color=green][color=darkred]
                      >>> x[][/color][/color][/color]
                      ()

                      (but should it really result in an empty tuple? wouldn't None be a bit
                      more Pythonic?)

                      </F>

                      Comment

                      • spam.noam@gmail.com

                        #12
                        Re: Allowing zero-dimensional subscripts

                        Hello,

                        Sybren Stuvel wrote:[color=blue]
                        > I think it's ugly to begin with. In math, one would write simply 'x'
                        > to denote an unsubscribed (ubsubscripted? ) 'x'. And another point, why
                        > would one call __getitem__ without an item to call?[/color]

                        I think that in this case, mathematical notation is different from
                        python concepts.

                        If I create a zero-dimensional array, with the value 5, like this:[color=blue][color=green][color=darkred]
                        >>> a = array(5)[/color][/color][/color]

                        I refer to the array object as "a", and to the int it stores as "a[]".

                        For example, I can change the value it holds by writing[color=blue][color=green][color=darkred]
                        >>> a[] = 8[/color][/color][/color]
                        Writing "a = 8" would have a completely different meaning - create a
                        new name, a, pointing at a new int, 8.

                        Noam

                        Comment

                        • spam.noam@gmail.com

                          #13
                          Re: Allowing zero-dimensional subscripts

                          Hello,

                          Fredrik Lundh wrote:[color=blue]
                          > (but should it really result in an empty tuple? wouldn't None be a bit
                          > more Pythonic?)[/color]

                          I don't think it would. First of all, x[()] already has the desired
                          meaning in numpy. But I think it's the right thing - if you think of
                          what's inside the brackets as a list of subscripts, one for each
                          dimension, which is translated to a call to __getitem__ or __setitem__
                          with a tuple of objects representing the subscripts, then an empty
                          tuple is what you want to represent no subscripts.

                          Of course, one item without a comma doesn't make a tuple, but I see
                          this as the special case - just like parentheses with any number of
                          commas are interpreted as tuples, except for parentheses with one item
                          without a comma.

                          (By the way, thanks for the tips for posting a PEP - I'll try to do it
                          quickly.)

                          Noam

                          Comment

                          • Antoon Pardon

                            #14
                            Re: Allowing zero-dimensional subscripts

                            Op 2006-06-08, spam.noam@gmail .com schreef <spam.noam@gmai l.com>:[color=blue]
                            > Hello,
                            >
                            > Terry Reedy wrote:[color=green][color=darkred]
                            >> > In a few more words: Currently, an object can be subscripted by a few
                            >> > elements, separated by commas. It is evaluated as if the object was
                            >> > subscripted by a tuple containing those elements.[/color]
                            >>
                            >> It is not 'as if'. 'a,b' *is* a tuple and the object *is* subcripted by a
                            >> tuple.
                            >> Adding () around the non-empty tuple adds nothing except a bit of noise.
                            >>[/color]
                            >
                            > It doesn't necessarily matter, but technically, it is not "a tuple".[/color]

                            Yes it is.
                            [color=blue]
                            > The "1, 2" in "x[1, 2]" isn't evaluated according to the same rules as
                            > in "x = 1, 2"[/color]

                            I was pretty sure it was.
                            [color=blue]
                            > - for example, you can have "x[1, 2:3:4, ..., 5]", which
                            > isn't a legal tuple outside of square braces[/color]

                            Yes it is, it just is illegal notation outside square brackets.
                            You could have approximate the same effect by

                            I = 1, slice(2,3,4), Ellipsis, 5
                            x[I]
                            [color=blue]
                            > - in fact, it even isn't
                            > legal inside parens: "x[(1, 2:3:4, ..., 5)]" isn't legal syntax.[/color]

                            But what is illegal is the notation, not the value.

                            --
                            Antoon Pardon

                            Comment

                            • spam.noam@gmail.com

                              #15
                              Re: Allowing zero-dimensional subscripts

                              Hello,

                              Following Fredrik's suggestion, I wrote a pre-PEP. It's available on
                              the wiki, at http://wiki.python.org/moin/EmptySubscriptListPEP and I
                              also copied it to this message.

                              Have a good day,
                              Noam


                              PEP: XXX
                              Title: Allow Empty Subscript List Without Parentheses
                              Version: $Revision$
                              Last-Modified: $Date$
                              Author: Noam Raphael <spam.noam@gmai l.com>
                              Status: Draft
                              Type: Standards Track
                              Content-Type: text/x-rst
                              Created: 09-Jun-2006
                              Python-Version: 2.5?
                              Post-History: 30-Aug-2002

                              Abstract
                              ========

                              This PEP suggests to allow the use of an empty subscript list, for
                              example ``x[]``, which is currently a syntax error. It is suggested
                              that in such a case, an empty tuple will be passed as an argument to
                              the __getitem__ and __setitem__ methods. This is consistent with the
                              current behaviour of passing a tuple with n elements to those methods
                              when a subscript list of length n is used, if it includes a comma.


                              Specification
                              =============

                              The Python grammar specifies that inside the square brackets trailing
                              an expression, a list of "subscripts ", separated by commas, should be
                              given. If the list consists of a single subscript without a trailing
                              comma, a single object (an ellipsis, a slice or any other object) is
                              passed to the resulting __getitem__ or __setitem__ call. If the list
                              consists of many subscripts, or of a single subscript with a trailing
                              comma, a tuple is passed to the resulting __getitem__ or __setitem__
                              call, with an item for each subscript.

                              Here is the formal definition of the grammar:

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

                              This PEP suggests to allow an empty subscript list, with nothing
                              inside the square brackets. It will result in passing an empty tuple
                              to the resulting __getitem__ or __setitem__ call.

                              The change in the grammar is to make "subscriptl ist" in the first
                              quoted line optional:

                              ::
                              trailer: '(' [arglist] ')' | '[' [subscriptlist] ']' | '.' NAME


                              Motivation
                              ==========

                              This suggestion allows you to refer to zero-dimensional arrays
                              elegantly. In
                              NumPy, you can have arrays with a different number of dimensions. In
                              order to refer to a value in a two-dimensional array, you write
                              ``a[i, j]``. In order to refer to a value in a one-dimensional array,
                              you write ``a[i]``. You can also have a zero-dimensional array, which
                              holds a single value (a scalar). To refer to its value, you currently
                              need to write ``a[()]``, which is unexpected - the user may not even
                              know that when he writes ``a[i, j]`` he constructs a tuple, so he
                              won't guess the ``a[()]`` syntax. If the suggestion is accepted, the
                              user will be able to write ``a[]`` in order to refer to the value, as
                              expected. It will even work without changing the NumPy package at all!

                              In the normal use of NumPy, you usually don't encounter
                              zero-dimensional arrays. However, the author of this PEP is designing
                              another library for managing multi-dimensional arrays of data. Its
                              purpose is similar to that of a spreadsheet - to analyze data and
                              preserve the relations between a source of a calculation and its
                              destination. In such an environment you may have many
                              multi-dimensional arrays - for example, the sales of several products
                              over several time periods. But you may also have several
                              zero-dimensional arrays, that is, single values - for example, the
                              income tax rate. It is desired that the access to the zero-dimensional
                              arrays will be consistent with the access to the multi-dimensional
                              arrays. Just using the name of the zero-dimensional array to obtain
                              its value isn't going to work - the array and the value it contains
                              have to be distinguished.


                              Rationale
                              =========

                              Passing an empty tuple to the __getitem__ or __setitem__ call was
                              chosen because it is consistent with passing a tuple of n elements
                              when a subscript list of n elements is used. Also, it will make NumPy
                              and similar packages work as expected for zero-dimensional arrays
                              without
                              any changes.

                              Another hint for consistency: Currently, these equivalences hold:

                              ::
                              x[i, j, k] <--> x[(i, j, k)]
                              x[i, j] <--> x[(i, j)]
                              x[i, ] <--> x[(i, )]
                              x[i] <--> x[(i)]

                              If this PEP is accepted, another equivalence will hold:

                              ::
                              x[] <--> x[()]


                              Backwards Compatibility
                              =============== ========

                              This change is fully backwards compatible, since it only assigns a
                              meaning to a previously illegal syntax.


                              Reference Implementation
                              =============== =========

                              Available as SF Patch no. 1503556.
                              (and also in http://python.pastebin.com/768317 )

                              It passes the Python test suite, but currently doesn't provide
                              additional tests or documentation.


                              Copyright
                              =========

                              This document has been placed in the public domain.

                              Comment

                              Working...