Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
[Python-ideas] List Revolution (python.org)
118 points by telemachos on Sept 10, 2011 | hide | past | favorite | 49 comments


Guido admits this is a joke later in the thread:

(And to those taking the thread seriously: this is all in jest. We won't change the indexing base. The idea is so preposterous that the only kind of response possible is to laugh with it.)

--Guido

http://mail.python.org/pipermail/python-ideas/2011-September...


The Dijkstra transcript referred to a bit deeper in the thread about why sequence numbering starts at zero is a tangentially interesting read: http://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EW...


I specifically paged through the read to make sure that link had been given, and then came to this comment page to do the same thing.

Few people seem to know that we have real and valid reasons for indexing from 0 instead of 1.


Apologies if this appears dumb. After going through the link I still could not understand why is it ok to exclude the upper bound while including the lower bound? Is it because the lower bound is fixed as 0 is the smallest natural number? Or is there some other reason.


Dijkstra explains it pretty clearly - there are two main reasons.

The first is so that the number of elements in the array/list/vector/collection is given by upper-lower.

The second is so that successive intervals re-use the same number, the upper bound of one becoming the lower bound of the next.

This is python we can have:

    L[:3], L[3:6], L[6:23], L[23:40], L[40:]
With the repeated numbers we know that all elements of L have been included. Further, we know that given:

    L[start:end]
... then (provided L had at least "end" elements to start with) the resulting length is end-start. If you included the end point then the length would be end-start+1 which is fertile ground for fence-post errors.


But both of those things would be true if you include the upper bound and don't include the lower bound. I.e. if an array with bounds 0 and 4 had items in positions 1, 2, 3, and 4.


Yes, and that question is covered in the Dijkstra paper.

If you're talking about numbers from 13 onwards, it doesn't really make sense to talk about numbers greater than 12. More specifically, if you start counting from 0 then it feels (to me) more natural to include the lower bound.

If you talk about {5 .. 13} then it feels easier to say

    "From 5 up to (but not including) 13,"
rather than saying

    "From 5, er, sorry, no, from *6* up to and including 13."
There is a question of taste here, as well as background and experience. Don't expect it to be "objectively proven."

http://www.paulgraham.com/taste.html

In the end it is all about convention, and what ends up making code cleaner, less error-prone, and more aesthetically pleasing. As I say, there are questions of taste and experience. Personally I find the Dijkstra/Python method for more consistent and pleasing than the alternatives.


Another reason: Wrap-around with modular reduction is a snug fit, so it's L[i % n] rather than L[1 + i % n]. You could have taken 1, 2, ..., n or indeed any set of n integers with distinct residue classes modulo n as the representatives, but the standard choice in mathematics is 0, 1, ..., n-1 for consistency with the division theorem.

It is often very inconvenient when mathematicians number from 1 instead of 0. A classic example is with Fourier matrices. Let w be a primitive nth root of unity. Then numbering as computer scientists, starting with 0, the formula is F(i,j) = w^(i j). But using the mathematician's convention, it is F(i,j) = w^((i-1)(j-1)). The same issue exists with all Vandermonde matrices.


Thanks for the explanation.


Roberto Ierusalimschy has an interesting perspective on the zero vs. one concept:

"Because people count from one, not zero.

We do that in kindergarten, in music, when starting a race, when drawing up an agenda, everywhere. One, two, three, etc have their counterparts in every known language on earth.

Zero, on the other hand, is an advanced concept. Humanity could prove that sqrt(2) is not a rational number centuries before anybody thought that a symbol for zero might be useful.

A harder question would be "why do arrays in some other languages count from zero not one?" The answer for C is a good one: "so that * (A+k) and A[k] mean the same". For Python, the answer seems to be "because it's that way in C"."

And:

"Currently, many languages are 0-based due to influence from C. Ironically, none of them share the reason that made C 0-based (where a[e] means * (a+e))."

(EDIT: I had to add spaces after the stars to prevent HN from italicizing a huge block of text.


Meanwhile, some people do count up from zero. At least in numbering floors in a building. I know in Europe and other parts of the world the ground floor is the zeroth floor, and it goes up from there.


Yeah, a lot of the buildings at my university are numbered that way. But not even in Europe would one count a stack of paper as "zero, one, two, three..."


Numerically, yes, but nobody calls it a "zeroth" floor. Rather, its "ground", "first", "second" (or G, 1, 2, 3...) so while ground is equivalent to zero, nobody actually says (or thinks) zero. At least, nowhere I've been.


So let's just call it the "ground" index.

  G = ground = 0;
  A[G], A[1], A[2], ...


Where I work, rooms on the 1st floor have numbers like 1.01, 1.02 etc., on the ground floor it's 0.01, 0.02 etc., and in the basement it's -1.01, -1.02 etc.

This is confusing for some people (unfamiliar with the situation), who need to go to a number in the basement but consistently turn up two floors higher.


> in music

Music uses both systems.

A chromatic approach uses a 0-indexed system while the classical diatonic scales and intervals are indexed at 1. A perfect 5th is a chromatic interval of 7 semitones.

1-do(0) 2-re(2) 3-me(4) 4-fa(5) 5-sol(7) 6-la(9) 7-ti(11)

The question is whether it's more useful to count the notes that appear and label them with numbers, or to measure the difference between them.


I often find 0-based indexing sneaking into other places too.

For example, imagine I want to fake an nm 2d matrix M with an array A, with nm elements

Then with 0-indexing, M[i][j] is stored at A[im+j]. With 1-indexing, M[i][j] is stored at A[(i-1)m+j].


I consider _counting_ and _indexing_ being two different concepts. In C, you declare int a[5], where 5 is the array size (element _count_), but its _indices_ run from 0 to 4. (Indeed, an array of size n can be also viewed as a _function_ with domain [0,n-1].)


And Japanese don't seem to even have a word for that until they "borrowed" it.


Good news! You can have this right now in Perl:

  $[ = 1;
Now all of your arrays are 1-indexed!


I am truly, truly horrified that this a language option in perl, although I'm not surprised. (Well, I did google it to see if you were joking, but you weren't, apparently).

The older I get the more Larry Wall strikes me as like a really well intentioned hippy type; when in God's green earth has it been a good idea to allow a five character statement change the truth values of nearly every for loop in a body of code?

Perl always claimed it gave you enough rope to hang yourself, but this goes far, far beyond that. This is like building the scaffolding and marking it like "Young developers, play here! Ropes are fun!"


1) It's not like the docs don't recommend against it.

2) As of Perl 5+ it's evaluated at compile-time rather than run-time, which is not as bad as if you could flip back and forth at runtime. Though you can use 'local' to lexically scope its effects -- hilarity ensues as you hand off said code to someone else for maintenance.

3) It's from a different era. As per the docs:

    Default is 0, but you could theoretically set
    it to 1 to make Perl behave more like awk (or
    Fortran)
It's there to help you emulate awk or Fortran... definitely targeted at today's young programmers. ;-)

[ Though the core of SciPy/NumPy is notably written in Fortran. Not quite as dead as some would have you believe. ]


> I am truly, truly horrified that this a language option in perl, although I'm not surprised.

How about this in C(and thousand others): #define if while

I am pretty sure I can find something to horrify you in almost any language.


Let's throw in a fun Python hack too:

    >>> import sys
    >>> import ctypes
    >>> pyint_p = ctypes.POINTER(ctypes.c_byte*sys.getsizeof(5))
    >>> five = ctypes.cast(id(5), pyint_p)
    >>> 2 + 2 == 5
    False
    >>> five.contents[five.contents[:].index(5)] = 4
    >>> 2 + 2 == 5
    True


May I ask how did you find about that? Sometime I would like to play in ctypes but I'm not sure where to start :-/

Here's a small snippet that let you add methods to built-ins:

  def inject(cls, wrapper=lambda x: x, name=None):
      def _builtin_hack(name):
          import ctypes as c
  
          _get_dict = c.pythonapi._PyObject_GetDictPtr
          _get_dict.restype = c.POINTER(c.py_object)
          _get_dict.argtypes = [c.py_object]
  
          return _get_dict(name).contents.value
  
      def wrap(method):
          name_ = name or method.func_name
          method = wrapper(method)
  
          try:
              setattr(cls, name_, method)
          except:
              _builtin_hack(cls)[name_] = method
  
      return wrap  


    @inject(dict)
    def extend(self, new_dict):
        return dict(self, **new_dict)

    print {'a':2}.extend({'b':3})


ctypes is like god-mode for Python... I like your hack too. I just play around with it from time to time, I believe the only "serious" thing I've done with it so far is making a Python interface around a C library I made.

I think I discovered the hack when I found out about the id() function, and hex(id(5)) looked suspiciously like a pointer value. (And http://docs.python.org/library/functions.html#id confirms.) http://docs.python.org/library/ctypes.html has usually been pretty useful. Apart from that, just play.


You can do anything in ctypes, though. :3

    $ python -c "import ctypes; ctypes.memset(0, 0, 42)"
    Segmentation fault


#defining reserved words is not permitted by standard C (or C++), although compilers do allow it in practice. Anyway, it's a totally different thing to abuse a general-purpose feature to do horrible thing X than to have a specific feature, only useful for doing horrible things, built into the language.


Or more subtly:

  #define break continue
Or Ruby:

  irb(main):001:0> if 0
  irb(main):002:1> print "True!"
  irb(main):003:1> end
  True!=> nil
(Though the Ruby example probably not as horrific as the others)


true the ruby should be a type error


It's deprecated in modern releases of Perl 5 and shall likely be removed.


Lua does this already. And that's the part about Lua that I don't like. But that's mostly my personal preference speaking.


He's joking right - I almost spit out my diet coke... (oh yeah...I'm sure THAT will accelerate my group's upgrade from 2.66....)


woah.

(not to post something useless, but I'm literally speechless going back and forth between "that's so awesome" and "that's so dumb" in my head for so many different reasons)

(and at how short and quick Guido's response was, as if it was such an easy decision to make.)


I suspect you're overlooking Guido's sense of humor. He was making a joke with his acceptance of the idea.


ah ok, not that familiar with Guido, but that makes much more sense haha

edit: also found this later in the thread to confirm the humor behind everything: http://mail.python.org/pipermail/python-ideas/2011-September...


Well, given Guido's endorsement, I think we need to change how these +1/-1 votes work. Clearly, +1 means what +0 used to mean. So you have to say +2 to vote in favor of something and -0 to vote against. I know it will be confusing during the transition period but it will be so much easier to use when we are done.

Loved this response http://mail.python.org/pipermail/python-ideas/2011-September...


First time I've laughed from a Python mailing list in a while.


That is clearly a freaking insane idea in a language as widely deployed as Python...


Don't worry, it's not going in until version 4, and version 3 isn't even the most common version yet.


Is that Python 3 or Python[3]??


It's a joke ;)


I sincerely hope so -- I looked and it wasn't April fool's day tho...


If a 1 offset under the system the guy advocates means what a 0 normally does, that implies that a +1 vote means the same thing as a +0 vote. So Guido is "agreeing" that it deserves +1, but only if you use 1-indexing so +1 is the lowest possible vote.


But +0 isn't the lowest possible vote in the current system... unless you want to claim that -1 is the highest possible vote because it wraps to the top of the scale.


An overzealous HTML sanitizer probably scrubbed the </sarcasm> tag. ;)


I don't want to live in this planet anymore.


The benevolent dictator for life has spoken!


I hope it's obvious that it's a joke, but was the question serious is my concern.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: