Arithmetic sequences in Python

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Gregory Petrosyan

    #1

    Arithmetic sequences in Python

    Please visit http://www.python.org/peps/pep-0204.html first.

    As you can see, PEP 204 was rejected, mostly because of not-so-obvious
    syntax. But IMO the idea behind this pep is very nice. So, maybe
    there's a reason to adopt slightly modified Haskell's syntax? Something
    like

    [1,3..10] --> [1,3,5,7,9]
    (1,3..10) --> same values as above, but return generator instead of
    list
    [1..10] --> [1,2,3,4,5,6,7,8 ,9,10]
    (1 ..) --> 'infinite' generator that yield 1,2,3 and so on
    (-3,-5 ..) --> 'infinite' generator that yield -3,-5,-7 and so on

    So,
    1) "[]" means list, "()" means generator
    2) the "start" is required, "step" and "end" are optional.

    Also, this can be nicely integrated with enumerations (if they will
    appear in python). Haskell is also example of such integration.

  • Bas

    #2
    Re: Arithmetic sequences in Python

    I like the use of the colon as in the PEP better: it is consistant with
    the slice notation and also with the colon operator in Matlab.

    I like the general idea and I would probably use it a lot if available,
    but the functionality is already there with range and irange.

    Bas

    Comment

    • Paul Rubin

      #3
      Re: Arithmetic sequences in Python

      "Gregory Petrosyan" <gregory.petros yan@gmail.com> writes:[color=blue]
      > As you can see, PEP 204 was rejected, mostly because of not-so-obvious
      > syntax. But IMO the idea behind this pep is very nice. So, maybe
      > there's a reason to adopt slightly modified Haskell's syntax?[/color]

      I like this with some issues: Python loops tend to be 0-based, so
      while it's convenient to express the sequence [1..n], what you usually
      want is [0..(n-1)] which is uglier.

      If you want to count down from f(n) to zero, in Haskell you might say

      [b, b-1 .. 0] where b=f(n)

      There's no "where" in Python, so what do you do?

      [f(n)-1, f(n)-2 .. 0]

      evaluates f twice (and might not even get the same result both times),
      while the traditional

      xrange(f(n)-1, -1, -1)

      only evaluates it once but is IMO repulsive.

      Anyway I've never liked having to use range or xrange to control
      Python loops. It's just kludgy and confusing. So I think your idea
      has potential but there's issues that have to be worked out.

      Comment

      • Gregory Petrosyan

        #4
        Re: Arithmetic sequences in Python

        _Consistentsy_ is what BDFL rejects, if I understand pep right. As for
        me, it's not too god to have similar syntax for really different tasks.
        And [1:10] is really not obvious, while [1..10] is.

        Comment

        • Steven D'Aprano

          #5
          Re: Arithmetic sequences in Python

          On Mon, 16 Jan 2006 01:01:39 -0800, Gregory Petrosyan wrote:
          [color=blue]
          > Please visit http://www.python.org/peps/pep-0204.html first.
          >
          > As you can see, PEP 204 was rejected, mostly because of not-so-obvious
          > syntax. But IMO the idea behind this pep is very nice. So, maybe
          > there's a reason to adopt slightly modified Haskell's syntax? Something
          > like
          >
          > [1,3..10] --> [1,3,5,7,9][/color]

          -1 on the introduction of new syntax. Any new syntax.

          (I reserve the right to change my mind if somebody comes up with syntax
          that I like, but in general, I'm *very* negative on adding to Python's
          clean syntax.)

          For finite sequences, your proposal adds nothing new to existing
          solutions like range and xrange. The only added feature this proposal
          introduces is infinite iterators, and they aren't particularly hard to
          make:

          def arithmetic_sequ ence(start, step=1):
          yield start
          while 1:
          start += step
          yield start

          The equivalent generator for a geometric sequence is left as an exercise
          for the reader.

          If your proposal included support for ranges of characters, I'd be more
          interested.



          --
          Steven.

          Comment

          • Paul Rubin

            #6
            Re: Arithmetic sequences in Python

            Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=blue]
            > For finite sequences, your proposal adds nothing new to existing
            > solutions like range and xrange.[/color]

            Oh come on, [5,4,..0] is much easier to read than range(5,-1,-1).
            [color=blue]
            > The only added feature this proposal
            > introduces is infinite iterators, and they aren't particularly hard to
            > make:
            >
            > def arithmetic_sequ ence(start, step=1):
            > yield start
            > while 1:
            > start += step
            > yield start[/color]

            Well, that would be itertools.count (start, step) but in general a simple
            expression is nicer than 5 lines of code.
            [color=blue]
            > If your proposal included support for ranges of characters, I'd be more
            > interested.[/color]

            There's something to be said for that. Should ['a'..'z'] be a list or
            a string?

            Comment

            • Xavier Morel

              #7
              Re: Arithmetic sequences in Python

              Paul Rubin wrote:[color=blue]
              > There's something to be said for that. Should ['a'..'z'] be a list or
              > a string?[/color]
              To me, the most obvious result would be either a range object as a
              result, or always a list/generator of objects (to stay perfectly
              consistent). If a range of numbers translate into a list of numbers,
              then a range of characters should likewise translate to a list of
              characters, and a join would be required to get a regular string. This
              also adds more consistency between the two proposals of the initial post
              (e.g. list-based range and generator-based range), for while the
              list-based range could be expanded into a string a generator-based one
              couldn't/shouldn't, and the abstraction breaks (because two constructs
              that should be more or less equivalent become extremely different and
              can't be swapped transparently).

              This would also be consistent with other languages providing a native
              "range" object such as Ruby or or Ada ranges.

              The only thing that bothers me about the initial proposal is that there
              would not, in fact, be any "range object", but merely a syntactic sugar
              for list/generator creation. Not that I really mind it, but, well,
              syntactic sugar for the purpose of syntactic sugar really doesn't bring
              much to the table.

              For those who'd need the (0..n-1) behavior, Ruby features something that
              I find quite elegant (if not perfectly obvious at first), (first..last)
              provides a range from first to last with both boundaries included, but
              (first...last) (notice the 3 periods) excludes the end object of the
              range definition ('a'..'z') is the range from 'a' to 'z' while
              ('a'...'z') only ranges from 'a' to 'y').

              Comment

              • bearophileHUGS@lycos.com

                #8
                Re: Arithmetic sequences in Python

                Ranges of letters are quite useful, they are used a lot in Delphi/Ada
                languages:
                "a", "b", "c", "d", "e"...

                I like the syntax [1..n], it looks natural enough to me, but I think
                the Ruby syntax with ... isn't much natural.
                To avoid bugs the following two lines must have the same meaning:
                [1..n-1]
                [1..(n-1)]

                If you don't want to change the Python syntax then maybe the
                range/xrange can be extended for chars too:

                xrange("a", "z")
                range("z", "a", -1)

                But for char ranges I think people usually don't want to stop to "y"
                (what if you want to go to "z" too? This is much more common than
                wanting to stop to "y"), so another possibility is to create a new
                function like xrange that generates the last element too:

                interval("a", "c") equals to iter("abc")
                interval(1, 3) equals to iter([1,2,3])
                interval(2, 0, -1) equals to iter([2,1,0])

                I have created such interval function, and I use it now and then.

                Bye,
                bearophile

                Comment

                • Steven D'Aprano

                  #9
                  Re: Arithmetic sequences in Python

                  On Mon, 16 Jan 2006 12:51:58 +0100, Xavier Morel wrote:
                  [color=blue]
                  > For those who'd need the (0..n-1) behavior, Ruby features something that
                  > I find quite elegant (if not perfectly obvious at first), (first..last)
                  > provides a range from first to last with both boundaries included, but
                  > (first...last) (notice the 3 periods)[/color]

                  No, no I didn't.

                  Sheesh, that just *screams* "Off By One Errors!!!". Python deliberately
                  uses a simple, consistent system of indexing from the start to one past
                  the end specifically to help prevent signpost errors, and now some folks
                  want to undermine that.

                  *shakes head in amazement*


                  --
                  Steven.

                  Comment

                  • Alex Martelli

                    #10
                    Re: Arithmetic sequences in Python

                    Paul Rubin <http://phr.cx@NOSPAM.i nvalid> wrote:
                    ...[color=blue]
                    > while the traditional
                    >
                    > xrange(f(n)-1, -1, -1)
                    >
                    > only evaluates it once but is IMO repulsive.[/color]

                    Yep, reversed(range( f(n))) is MUCH better.


                    Alex

                    Comment

                    • Alex Martelli

                      #11
                      Re: Arithmetic sequences in Python

                      Paul Rubin <http://phr.cx@NOSPAM.i nvalid> wrote:
                      [color=blue]
                      > Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=green]
                      > > For finite sequences, your proposal adds nothing new to existing
                      > > solutions like range and xrange.[/color]
                      >
                      > Oh come on, [5,4,..0] is much easier to read than range(5,-1,-1).[/color]

                      But not easier than reversed(range( 6)) [[the 5 in one of the two
                      expressions in your sentence has to be an offbyone;-)]]


                      Alex

                      Comment

                      • Alex Martelli

                        #12
                        Re: Arithmetic sequences in Python

                        Steven D'Aprano <steve@REMOVETH IScyber.com.au> wrote:
                        [color=blue]
                        > On Mon, 16 Jan 2006 12:51:58 +0100, Xavier Morel wrote:
                        >[color=green]
                        > > For those who'd need the (0..n-1) behavior, Ruby features something that
                        > > I find quite elegant (if not perfectly obvious at first), (first..last)
                        > > provides a range from first to last with both boundaries included, but
                        > > (first...last) (notice the 3 periods)[/color]
                        >
                        > No, no I didn't.
                        >
                        > Sheesh, that just *screams* "Off By One Errors!!!". Python deliberately
                        > uses a simple, consistent system of indexing from the start to one past
                        > the end specifically to help prevent signpost errors, and now some folks
                        > want to undermine that.
                        >
                        > *shakes head in amazement*[/color]

                        Agreed. *IF* we truly needed an occasional "up to X *INCLUDED*"
                        sequence, it should be in a syntax that can't FAIL to be noticed, such
                        as range(X, endincluded=Tru e).


                        Alex

                        Comment

                        • Steven D'Aprano

                          #13
                          Re: Arithmetic sequences in Python

                          On Mon, 16 Jan 2006 02:58:39 -0800, Paul Rubin wrote:
                          [color=blue]
                          > Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=green]
                          >> For finite sequences, your proposal adds nothing new to existing
                          >> solutions like range and xrange.[/color]
                          >
                          > Oh come on, [5,4,..0] is much easier to read than range(5,-1,-1).[/color]

                          Only in isolation, and arguably not even then. Or do you think that Perl
                          is much easier to read than Python simply because you can write your
                          programs in fewer characters?

                          It looks too much like the list [5,4,0], and is easy to make typos:
                          [5,4,.0] gives you no syntax error but very different results.

                          The meaning isn't particular clear: is it supposed to be [start, stop,
                          step] (the natural expectation for those used to Python slices and ranges)
                          or [start, next, stop]? It is actually the second, but go back to the
                          original post by Gregory: after giving examples, he still wrongly
                          described his proposal as having a "step" parameter. There is no step
                          parameter -- the step is implied, by subtracting start from next. Such
                          confusion doesn't bode well.

                          Python indexing deliberately goes to one-past-the-end counting for a
                          reason: it helps prevent off-by-one signpost errors. This syntax goes
                          against that decision, and adds one more thing to memorise about Python:
                          the end index is not included in the list, except for arithmetic
                          sequences, where it is, sometimes but not necessarily. In [5,6,10] the end
                          index 10 is included; in [5,7,10] it isn't.

                          You've picked the most awkward example of range, I admit. But let's look
                          at a few others:

                          [0,..9] versus range(10)
                          [55, ...73] versus range(55, 74)
                          [1, 3, ..len(mystr)] versus range(1, len(mystr)+1, 2)
                          [55, 65, 295] versus range(55, 296, 10)

                          How often do you find yourself knowing the first two terms of a sequence
                          but not the step size anyway? Is that a common use case?


                          [color=blue][color=green]
                          >> The only added feature this proposal
                          >> introduces is infinite iterators, and they aren't particularly hard to
                          >> make:
                          >>
                          >> def arithmetic_sequ ence(start, step=1):
                          >> yield start
                          >> while 1:
                          >> start += step
                          >> yield start[/color]
                          >
                          > Well, that would be itertools.count (start, step) but in general a simple
                          > expression is nicer than 5 lines of code.[/color]

                          I didn't say that my generator was the only way to produce the required
                          result, I was pointing out how simple it is. Yes, itertools is the way to
                          go for this sort of thing.

                          [color=blue][color=green]
                          >> If your proposal included support for ranges of characters, I'd be more
                          >> interested.[/color]
                          >
                          > There's something to be said for that. Should ['a'..'z'] be a list or a
                          > string?[/color]

                          It uses [ something ] syntax, so for consistency with lists and list
                          comprehensions it should be a list.

                          But a string would be more practical, since list(['a'..'z']) is easier and
                          more intuitive than ''.join(['a'..'z']). But I'm not sure that it is
                          *that* much more practical to deserve breaking the reader's expectation.

                          So I think the best thing would be to create itertools.chars ('a', 'z') or
                          similar, not new syntax.


                          --
                          Steven.

                          Comment

                          • Roy Smith

                            #14
                            Re: Arithmetic sequences in Python

                            Alex Martelli <aleax@mail.com cast.net> wrote:[color=blue]
                            >Agreed. *IF* we truly needed an occasional "up to X *INCLUDED*"
                            >sequence, it should be in a syntax that can't FAIL to be noticed, such
                            >as range(X, endincluded=Tru e).[/color]

                            How about...

                            for i in (0..x]:
                            blah

                            Comment

                            • Alex Martelli

                              #15
                              Re: Arithmetic sequences in Python

                              Roy Smith <roy@panix.co m> wrote:
                              [color=blue]
                              > Alex Martelli <aleax@mail.com cast.net> wrote:[color=green]
                              > >Agreed. *IF* we truly needed an occasional "up to X *INCLUDED*"
                              > >sequence, it should be in a syntax that can't FAIL to be noticed, such
                              > >as range(X, endincluded=Tru e).[/color]
                              >
                              > How about...
                              >
                              > for i in (0..x]:
                              > blah[/color]

                              The difference between a round parenthesis and a square bracket can
                              EASILY be overlooked, depending partly on what font you're using.


                              Alex

                              Comment

                              Working...