Python less error-prone than Java

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Christoph Zwerschke

    #16
    Re: Python less error-prone than Java

    Kaz Kylheku wrote:[color=blue]
    > You can have statically typed languages with inadequate type safety,
    > and you can have dynamically typed languages with inadequate type
    > safety.[/color]

    But the point in this example was that the Java program ironically had
    the bug *because* Java handles ints in a type-safe way, while Python
    does not.
    [color=blue][color=green]
    >> What's better about the Python version? First, it will operate on
    >> *any* sorted array, no matter which type the values have.[/color]
    >
    > Uh huh! With hard-coded < and = operators, how stupid. What if you
    > want to use it on strings?
    > Would that be a case-insensitive lexicographic comparison, or
    > case-insensitive? How do you specify what kind of less-than and equal
    > you want to do?[/color]

    Where's the problem? The function uses the standard ordering of the
    values you feed to it, i.e. case-insensitive lexicographical order if
    you feed a lis of ordinary tuples of strings. You can also feed objects
    with a different ordering, like case-insensitive.

    Anyway, that was completely not the point. The point was that you could
    take that Java program, convert it directly to Python, and have
    automatically eliminated a bug. I did not claim that the resulting
    Python program was automatically a real good and Pythonic one.
    [color=blue]
    > -1 to indicate not found? Why copy Java braindamage induced by an
    > antiquated form of static typing? The Java version has to do that[/color]

    So you would call Python's str.find() method braindamaged as well?

    But as I said, that was not the point here anyway.

    -- Christoph

    Comment

    • nikie

      #17
      Re: Python less error-prone than Java

      Let's look at two different examples: Consider the following C# code:

      static decimal test() {
      decimal x = 10001;
      x /= 100;
      x -= 100;
      return x;
      }

      It returns "0.01", as you would expect it. Now, consider the python
      equivalent:

      def test():
      x = 10001
      x /= 100
      x -= 100
      return x

      It returns "0". Clearly an error!
      Even if you used "from __future__ import division", it would actually
      return "0.010000000000 005116", which, depending on the context, may
      still be an intolerable error.

      Morale: the problem isn't whether the the types are chosen at
      compile-time or at runtime, it's simply _what_ type is chosen, and
      whether it's appropriate or not.

      I can even think of an example where C's (and Java's) bounded ints are
      the right choice, while Python's arbitraty-precision math isn't: Assume
      you get two 32-bit integers containing two time values (or values from
      an incremental encoder, or counter values). How do you find out how
      many timer ticks (or increments, or counts) have occured between those
      two values, and which one was earlier? In C, you can just write:

      long Distance(long t1, long t0) { return t1-t0; }

      And all the wraparound cases will be handled correctly (assuming there
      have been less than 2^31 timer ticks between these two time values).
      "Distance" will return a positive value if t1 was measured after t0, a
      negative value otherwise, even if there's been a wraparound in between.
      Try the same in Python and tell me which version is simpler!

      Comment

      • D H

        #18
        Re: Python less error-prone than Java

        Christoph Zwerschke wrote:[color=blue]
        >
        > See the following web page if you dont find it ;-)
        > http://googleresearch.blogspot.com/2...it-nearly.html[/color]

        The point of that is that it did fail. It threw an
        ArrayIndexOutOf BoundsException exception. But it was just luck that
        happened. Unfortunately I don't think java and C# have integer overflow
        checking turned on by default.

        Take this longArithmetic benchmark here:

        and a story about it here:


        The java and C# versions are fast (15 seconds for me), BUT, they
        give the incorrect result because of an overflow error.
        The python version gives the correct result because it transparently
        changes the underlying types to handle the larger numbers, BUT this
        causes it to run over 20X slower than Java or C#. It takes 10 minutes
        to complete in python, not 15 seconds. With psyco, it takes 5 minutes.

        So to say the story you pointed out shows that python is superior
        is a matter of perspective. Yes, python gave the correct result
        by silently changing the underlying types to longs, and that is
        what I would expect of a scripting language. But the price is
        speed. In both these cases, I would rather be made aware of the
        error in the code and fix it so I didn't have to suffer slowdowns.

        That is why in boo ( http://boo.codehaus.org/ ) luckily overflow
        checking is enabled by default, and it throws a overflow exception at
        runtime to tell you something is wrong with your code. When you
        then fix for that, you get the same 15 second time just like java
        and C#.

        Comment

        • Christoph Zwerschke

          #19
          Re: Python less error-prone than Java

          nikie wrote:[color=blue]
          > Let's look at two different examples: Consider the following C# code:
          >
          > static decimal test() {
          > decimal x = 10001;
          > x /= 100;
          > x -= 100;
          > return x;
          >
          > It returns "0.01", as you would expect it.[/color]

          Yes, I would expect that because I have defined x as decimal, not int.
          [color=blue]
          > Now, consider the python equivalent:
          >
          > def test():
          > x = 10001
          > x /= 100
          > x -= 100
          > return x[/color]

          No, that's not the Python equivalent. The equivalent of the line

          decimal x = 10001

          in Python would be

          x = 10001.0

          or even:

          from decimal import Decimal
          x = Decimal(10001)

          Setting x = 10001 would be equivalent to the C# code

          int x = 10001
          [color=blue]
          > It returns "0". Clearly an error![/color]

          That's not clearly an error. If you set int x = 10001 in C#, then you
          also get a "0". By setting x to be an integer, you are implicitely
          telling Python that you are not interested in fractions, and Python does
          what you want. Granted, this is arguable and will be changed in the
          __future__, but I would not call that an error.

          By the way, the equivalent Python code to your C# program gives on my
          machine the very same result:[color=blue][color=green][color=darkred]
          >>> x = 10001.0; x /= 100; x -= 100; print x[/color][/color][/color]
          0.01
          [color=blue]
          > Even if you used "from __future__ import division", it would actually
          > return "0.010000000000 005116", which, depending on the context, may
          > still be an intolerable error.[/color]

          With from __future__ import division, I also get 0.01 printed. Anyway,
          if there are small discrepancies then these have nothing to do with
          Python but rather with the underlying floating-point hardware and C
          library, the way how you print the value and the fact that 0.01 can
          principally not be stored exactly as a float (nor as a C# decimal), only
          as a Python Decimal.
          [color=blue]
          > I can even think of an example where C's (and Java's) bounded ints are
          > the right choice, while Python's arbitraty-precision math isn't:
          > Assume you get two 32-bit integers containing two time values (or
          > values from an incremental encoder, or counter values). How do you
          > find out how many timer ticks (or increments, or counts) have occured
          > between those two values, and which one was earlier? In C, you can
          > just write:
          >
          > long Distance(long t1, long t0) { return t1-t0; }
          >
          > And all the wraparound cases will be handled correctly (assuming there
          > have been less than 2^31 timer ticks between these two time values).
          > "Distance" will return a positive value if t1 was measured after t0, a
          > negative value otherwise, even if there's been a wraparound in
          > between. Try the same in Python and tell me which version is simpler![/color]

          First of all, the whole problem only arises because you are using a
          statically typed counter ;-) And it only is easy in C when your counter
          has 32 bits. But what about a 24 bit counter?

          Anyway, in Python, you would first define:

          def wrap(x, at=1<<31):
          if x < -at:
          x += at*2
          elif x >= at:
          x -= at*2
          return x

          Then, the Python program would be as simple:

          Distance = lambda t1,t0: wrap(t1-t0)

          -- Christoph

          Comment

          • nikie

            #20
            Re: Python less error-prone than Java

            Christoph Zwerschke wrote:
            [color=blue]
            > nikie wrote:[color=green]
            > > Let's look at two different examples: Consider the following C# code:
            > >
            > > static decimal test() {
            > > decimal x = 10001;
            > > x /= 100;
            > > x -= 100;
            > > return x;
            > >
            > > It returns "0.01", as you would expect it.[/color]
            >
            > Yes, I would expect that because I have defined x as decimal, not int.
            >[color=green]
            > > Now, consider the python equivalent:
            > >
            > > def test():
            > > x = 10001
            > > x /= 100
            > > x -= 100
            > > return x[/color]
            >
            > No, that's not the Python equivalent. The equivalent of the line
            >
            > decimal x = 10001
            >
            > in Python would be
            >
            > x = 10001.0
            >
            > or even:
            >
            > from decimal import Decimal
            > x = Decimal(10001)[/color]

            Hm, then I probably didn't get your original point: I thought your
            argument was that a dynamically typed language was "safer" because it
            would choose the "right" type (in your example, an arbitrary-pecision
            integer) automatically. As you can see from the above sample, it
            sometimes picks the "wrong" type, too. Now you tell me that this
            doesn't count, because I should have told Python what type to use. But
            shouldn't that apply to the Java binary-search example, too? I mean,
            you could have told Java to used a 64-bit or arbitrary-length integer
            type instead of a 32-bit integer (which would actually be equivalent to
            the Python code), so it would do the same thing as the Python binary
            search implementation.
            [color=blue]
            > ...
            > By the way, the equivalent Python code to your C# program gives on my
            > machine the very same result:[color=green][color=darkred]
            > >>> x = 10001.0; x /= 100; x -= 100; print x[/color][/color]
            > 0.01[/color]

            Try entering "x" in the interpreter, and read up about the difference
            between str() and repr().
            [color=blue]
            >[color=green]
            > > Even if you used "from __future__ import division", it would actually
            > > return "0.010000000000 005116", which, depending on the context, may
            > > still be an intolerable error.[/color]
            >
            > With from __future__ import division, I also get 0.01 printed. Anyway,
            > if there are small discrepancies then these have nothing to do with
            > Python but rather with the underlying floating-point hardware and C
            > library, the way how you print the value and the fact that 0.01 can
            > principally not be stored exactly as a float (nor as a C# decimal), only
            > as a Python Decimal.[/color]

            The is OT, but what makes you think a C# decimal can't store 0.01?
            [color=blue][color=green]
            > > I can even think of an example where C's (and Java's) bounded ints are
            > > the right choice, while Python's arbitraty-precision math isn't:
            > > Assume you get two 32-bit integers containing two time values (or
            > > values from an incremental encoder, or counter values). How do you
            > > find out how many timer ticks (or increments, or counts) have occured
            > > between those two values, and which one was earlier? In C, you can
            > > just write:
            > >
            > > long Distance(long t1, long t0) { return t1-t0; }
            > >
            > > And all the wraparound cases will be handled correctly (assuming there
            > > have been less than 2^31 timer ticks between these two time values).
            > > "Distance" will return a positive value if t1 was measured after t0, a
            > > negative value otherwise, even if there's been a wraparound in
            > > between. Try the same in Python and tell me which version is simpler![/color]
            >
            > First of all, the whole problem only arises because you are using a
            > statically typed counter ;-) And it only is easy in C when your counter
            > has 32 bits. But what about a 24 bit counter?[/color]

            Easy, multiply it with 256 and it's a 32-bit counter ;-)
            Fortunately, 24-bit-counters are quite rare. 16-bit or 32-bit counters
            on the other hand are quite common, especially when you're working
            close to the hardware (where C is at home). All I wanted to point out
            is that bounded integers do have their advantages, because some people
            in this thread apparently have never stumbled over them.

            Comment

            • Alan Morgan

              #21
              Re: Python less error-prone than Java

              In article <e5u858$a1q$1@o nline.de>,
              Christoph Zwerschke <cito@online.de > wrote:[color=blue][color=green][color=darkred]
              >>> Simon Percivall wrote:
              >>>> First: It's perfectly simple in Java to create a binary sort that
              >>>> sorts all arrays that contain objects; so wrong there.
              >>> My point was that the *same* Java source example, directly converted to
              >>> Python would *automatically* accept all kinds of arrays.[/color]
              >>
              >> And the same code converted to SML would automatically work on all
              >> kinds of arrays and SML is statically typed. It's a language issue,
              >> not a typing issue.[/color]
              >
              >Ok, here the point was that Java has *explicit* static typing. SML is
              >not a procedural language and uses *implicit* static typing. Therefore
              >it shares some of the benefits of dynamically typed languages such as
              >Python. However, an SML version of the program would probably still have
              >the same bug as the Java version, right?
              >[color=green][color=darkred]
              >>> No need to make any extra efforts.
              >>> By the way, how would you do it in Java? With
              >>> function overloading? I would not call that perfectly simple.[/color]
              >>
              >> Since Java doesn't allow function overloading that clearly can't be
              >> the way. J2SE 5.0 allows generic classes and functions that operate
              >> on generic containers. There are some gotchas, but it's not drastically
              >> more complex than the original int-only java code.[/color]
              >
              >Java doesn't allow function overloading?[/color]

              Brain fart. You said "function" and I read "operator".

              Alan
              --
              Defendit numerus

              Comment

              • Christoph Zwerschke

                #22
                Re: Python less error-prone than Java

                nikie wrote:[color=blue]
                > Hm, then I probably didn't get your original point: I thought your
                > argument was that a dynamically typed language was "safer" because it
                > would choose the "right" type (in your example, an arbitrary-pecision
                > integer) automatically.[/color]

                No, my point was not to make a general statement. It just stumbled over
                that example and said to myself "that wouldn't have happend with
                Python." And I thought it might be interesting for people on c.l.p as
                well. That was all.
                [color=blue]
                > As you can see from the above sample, it
                > sometimes picks the "wrong" type, too. Now you tell me that this
                > doesn't count, because I should have told Python what type to use.[/color]

                Yes. Python did not "pick" that type - you explicitely said that x
                should an int by setting x = 10001.
                [color=blue]
                > I mean, you could have told Java to used a 64-bit or arbitrary-length
                > integer type instead of a 32-bit integer (which would actually be
                > equivalent to the Python code), so it would do the same thing
                > as the Python binary search implementation.[/color]

                Right, but then Java would do all index operations in that type, even
                for very small arrays when it's not necessary. That's why people
                probably don't do it.
                [color=blue]
                > The is OT, but what makes you think a C# decimal can't store 0.01?[/color]

                A C# data type summary gave me the impression that it was just a more
                accurate but still binary floating point type. But you're right, the
                name "decimal" should have given me a clue that it uses base 10 ;-)

                So sorry for the confusion. Forget what I wrote about float. I should
                have corretly written that the equivalent to the C# statement

                decimal x = 10001;

                is the following Python statement

                x = Decimal(10001)

                If you do the equivalent thing, Python will give the same result as C#.
                [color=blue]
                > All I wanted to point out is that bounded integers do have their
                > advantages, because some people in this thread apparently have
                > never stumbled over them.[/color]

                Sure, I did not want to deny that. The main advantages are speed, and
                dealing with hardware related issues. Your Distance function in C is of
                course much faster than my Python implementation. Surely I wouldn't want
                to write a device driver in Python.

                -- Christoph

                Comment

                • Ilpo Nyyssönen

                  #23
                  Re: Python less error-prone than Java

                  "Kaz Kylheku" <kkylheku@gmail .com> writes:
                  [color=blue]
                  > Buggy library code is what prompted that article.[/color]

                  Yes, but it is an error type that happens very rarely still. And so it
                  seems that very few programs even notice that bug in that library.
                  [color=blue]
                  > Except when you feed those programs inputs which are converted to
                  > integers which are then fed as domain values into some operation that
                  > doesn't fit into the range type.[/color]

                  If the input value range is limited, you want to get an error, if out
                  of range value is given. If you want to handle unlimited values, you
                  really need to take a look that you can do it. Think for example
                  storing such value to a database.
                  [color=blue][color=green]
                  >> 1. null pointer errors
                  >> 2. wrong type (class cast in Java, some weird missing attribute in python)
                  >> 3. array/list index out of bounds
                  >>
                  >> First and third ones are the same in about every language.[/color]
                  >
                  > ... other than C and C++, where their equivalents just crash or stomp
                  > over memory, but never mind; who uses those? ;)[/color]

                  It is not different. Your crash can tell you that it was a null
                  pointer. Your crash can tell you that you stomped over memory. You
                  just get the information about the error in different way.
                  [color=blue]
                  > Instead of this stupid idea of pointers or references having a null
                  > value, you can make a null value which has its own type, and banish
                  > null pointers.[/color]

                  Yes and I actually think that as bad thing. It is nice to be able to
                  tell the difference between null pointer and wrong type. Of course if
                  the error message tells you that you had null there, it is not a
                  problem, but what if you somehow lose the error message and get only
                  the exception class name? (Yes, you should always keep the message
                  too, but it does happen.)

                  --
                  Ilpo Nyyssönen # biny # /* :-) */

                  Comment

                  • Martin v. Löwis

                    #24
                    Re: Python less error-prone than Java

                    Ilpo Nyyssönen wrote:[color=blue][color=green]
                    >> Buggy library code is what prompted that article.[/color]
                    >
                    > Yes, but it is an error type that happens very rarely still. And so it
                    > seems that very few programs even notice that bug in that library.[/color]

                    That's certainly the case. The bug went unnoticed in the Java library
                    for nearly a decade, despite Java being used fairly widely.

                    The OP's point is not that the bug might be "minor": the point is that
                    an algorithm who was studied hundreds of times in computer science
                    courses, repeated many times in the literature, and proven "correct"
                    many times, still is wrong, and that the error primarily arises from
                    using a type declaration.
                    [color=blue]
                    > If the input value range is limited, you want to get an error, if out
                    > of range value is given. If you want to handle unlimited values, you
                    > really need to take a look that you can do it. Think for example
                    > storing such value to a database.[/color]

                    So the real design flaw in Java is that int addition doesn't raise
                    exceptions on overflow? That wouldn't have helped - the algorithm
                    still would have been wrong, and people still would have noticed
                    only when it happens (just as they get an exception now: array index
                    out of bounds)

                    Regards,
                    Martin

                    Comment

                    • Martin v. Löwis

                      #25
                      Re: Python less error-prone than Java

                      Christoph Zwerschke wrote:[color=blue]
                      > Anyway, in Python, you would first define:
                      >
                      > def wrap(x, at=1<<31):
                      > if x < -at:
                      > x += at*2
                      > elif x >= at:
                      > x -= at*2
                      > return x
                      >
                      > Then, the Python program would be as simple:
                      >
                      > Distance = lambda t1,t0: wrap(t1-t0)[/color]

                      In Python 2.4 and later, you could write

                      def Distance(t1, t0, maxint=(1<<32)-1):
                      return (t1-t0) & maxint

                      Like your code, this also extends to 24-bit integers or 64-bit
                      integers.

                      Regards,
                      Martin

                      Comment

                      • Christoph Zwerschke

                        #26
                        Re: Python less error-prone than Java

                        Martin v. Löwis wrote:[color=blue]
                        > In Python 2.4 and later, you could write
                        >
                        > def Distance(t1, t0, maxint=(1<<32)-1):
                        > return (t1-t0) & maxint[/color]

                        No, this function behaves differently. It never returns a negative
                        value. The only difference in Python 2.4 is that 1<<32 was 0 before.

                        -- Christoph

                        Comment

                        • Christoph Zwerschke

                          #27
                          Re: Python less error-prone than Java

                          Ilpo Nyyssönen wrote:[color=blue]
                          > It is not different. Your crash can tell you that it was a null
                          > pointer. Your crash can tell you that you stomped over memory. You
                          > just get the information about the error in different way.[/color]

                          Not all stomping over memory must result in a crash. You might just get
                          wrong results, and you don't notice it. Also, if you get such a crash
                          it's much harder to find out the reason. It may show off only later in a
                          different part of the program.

                          -- Chris

                          Comment

                          Working...