in reply to Re^7: Ansi Perl
in thread Ansi Perl

*blink*

Are you suggesting you have never heard of programs broken because of an upgrade of Perl? Where do you live? Mars?

Here's a goodie, which both shows the lack of standards, and the breakage of upgrades. Look at the following program:

sub AUTOLOAD {print $AUTOLOAD} *foo = bar; foo ();
Three questions:
  1. The program should print:
    1. main::foo
    2. main::bar
    3. Something else
  2. perl5.005_03 prints:
    1. main::foo
    2. main::bar
    3. Something else
  3. perl5.6.0 prints:
    1. main::foo
    2. main::bar
    3. Something else
Without actually running the program, but with consultation of all the documentation that comes with Perl, and any version of the Camel you like, could you answer all questions correctly?

Here's another program:

my %hash = (foo => 'bar'); chop for values %hash; print values %hash, "\n";
The program prints ba when run with 5.8.6, but it prints bar when run with 5.005_03. And that wasn't a bug fix.

Third program:

print 80.101.114.108;
Prints 80.101114.108 in 5.005_03 and earlier, but prints Perl from 5.6.0 onwards. You might say that noone writes 80.101.114.108 in normal program, and that's true. But evalled computer generated code can.

I'm not saying these examples are huge problems, and it takes a lot resources to fix. But breakage does happen. Over and over and over again. And it does take resources to find the breakage. And for large organisations running a myriad of programs, that is a problem.

Replies are listed 'Best First'.
Re: Ansi Perl
by jonadab (Parson) on Dec 28, 2004 at 05:37 UTC

    You're making my point for me. All of your examples (ab)use the same sorts of nooks and crannies of the language that the OP readily admits have to be avoided by C programmers in order to avoid breakage.

    The first example combines autoloading with typeglobs in a way that the Camel book doesn't even think about addressing. As you point out yourself, the questions you ask cannot be answered from the documentation and the Camel, which implies that the code represents undefined behavior. How is this any different from the undefined behavior in C, if you program outside the ANSI spec by targetting a specific compiler and OS?

    The second example plays games with aliasing, again in an obscure and AFAIK undocumented corner of the language.

    The third example tries to abuse barewords, which have been heavily deprecated since the Perl4 days and have been throwing warnings since 5.003 at least. Anybody who writes something like that in production code deserves whatever he gets, and it is trivial to find similar examples of nonstandard code breaking in C due to something as minor as compiling for a differently-endian hardware, to say nothing of switching compilers.

    If you write your code based on the information in the 2nd edition Camel book, it will work in all Perl versions from 5.003 forward; if there is even a single counterexample to this, I am not aware of it. (Feel free to point it out...) Needing to avoid the undocumented nooks and crannies is no worse in Perl than it is in C. When issues like endianness are considered, I maintain my previous assertion: Perl is more standardized than ANSI C.


    "In adjectives, with the addition of inflectional endings, a changeable long vowel (Qamets or Tsere) in an open, propretonic syllable will reduce to Vocal Shewa. This type of change occurs when the open, pretonic syllable of the masculine singular adjective becomes propretonic with the addition of inflectional endings."  — Pratico & Van Pelt, BBHG, p68
      The first example combines autoloading with typeglobs in a way that the Camel book doesn't even think about addressing.

      But the Camel discusses autoloading, and it discusses typeglobs. Sure, it doesn't discuss combining them, but it doesn't discuss combining autoloading and splicing either. Does that mean the use of splice inside an autoload routine is "undefined behaviour"? If not, then what determines which undiscussed combination of discussed techniques is "undefined" behaviour, and what isn't?

      The second example plays games with aliasing, again in an obscure and AFAIK undocumented corner of the language.

      Bzzzt! Thank you for playing.

      From the 5.005_03 perlfunc manual page:

      values HASH
              Returns a list consisting of all the values of the named hash.
              (In a scalar context, returns the number of values.)  The
              values are returned in an apparently random order.  The actual
              random order is subject to change in future versions of perl,
              but it is guaranteed to be the same order as either the keys()
              or each() function would produce on the same (unmodified) hash.
       
              Note that you cannot modify the values of a hash this way,
              because the returned list is just a copy.  You need to use a
              hash slice for that, since it's lvaluable in a way that
              values() is not.
       
                  for (values %hash)      { s/foo/bar/g }   # FAILS!
                  for (@hash{keys %hash}) { s/foo/bar/g }   # ok
       
              As a side effect, calling values() resets the HASH's internal
              iterator.  See also keys(), each(), and sort().
      
      (Emphasis mine). But from the 5.8.x manual:
      values HASH
              Returns a list consisting of all the values of the named hash.
              (In a scalar context, returns the number of values.)
       
              The values are returned in an apparently random order.  The
              actual random order is subject to change in future versions of
              perl, but it is guaranteed to be the same order as either the
              "keys" or "each" function would produce on the same (unmodi-
              fied) hash.  Since Perl 5.8.1 the ordering is different even
              between different runs of Perl for security reasons (see "Algo-
              rithmic Complexity Attacks" in perlsec).
      
              As a side effect, calling values() resets the HASH's internal
              iterator, see "each". (In particular, calling values() in void
              context resets the iterator with no other overhead.)
       
              Note that the values are not copied, which means modifying them
              will modify the contents of the hash:
       
                  for (values %hash)      { s/foo/bar/g }   # modifies %hash values
                  for (@hash{keys %hash}) { s/foo/bar/g }   # same
              
              See also "keys", "each", and "sort".
      

      The third example tries to abuse barewords, which have been heavily deprecated since the Perl4 days and have been throwing warnings since 5.003 at least.

      Did you actually look at the code? Here's it again:

      print 80.101.114.108;
      No bare words in this piece of code, and no version of Perl issues a warning.
      $ perl5.00503 -wle 'print $]; print 80.101.114.108' 5.00503 80.101114.108 $ perl5.8.6 -wle 'print $]; print 80.101.114.108' 5.008006 Perl
      See, no warnings. And for your information, in 5.005_03, 80.101.114.108 isn't a bareword. It's the concatenation of two floating point numbers. In 5.8.6, it's a v-string (which as shown are in another thread, are on their way out, so the program above is probably not going to print "Perl" in 5.10 or 5.12).
        Note also that the combination of autoloading and aliasing is exactly what AutoLoader.pm is doing. Which is part of the core distribution. And which is documented in the second edition of the Camel. Chapter 7.2.
Re^9: Ansi Perl
by Corion (Patriarch) on Dec 27, 2004 at 17:07 UTC

    Sorry, but I think you're using the wrong Perls then. Between every major version of Perl (the 5.5.x train, the 5.6.x train, the 5.8.x train ("stable") and the 5.9.x / 5.10.x train ("blead")), new features get introduced, 5.8 introduced PerlIO and Unicode in a wide range, 5.10 will have new stuff I don't know. If you need to use certain features and rely on certain features that are not commonly used, don't move your program to a new major Perl version before thouroughly testing it.

    Of course, if you don't supply the version of Perl your script is used with, you will need to test your script against all versions of Perl, but at least the future versions of Perl go through prereleases ("Release Candidates") before becoming public, and so you have some chance of getting an early warning by testing your program against bleadperl.

      Eh, I wasn't discussing new features. Dragonchild asked for examples of things that broke existing programs. I gave them. Add Unicode (should) not break program that don't use Unicode. New stuff should not break existing programs. And p5p is trying to not break programs. But program do get broken. As the examples showed. Stating I'm using the wrong Perls doesn't make any sense in this context.

      If you need to use certain features and rely on certain features that are not commonly used, don't move your program to a new major Perl version before thouroughly testing it.

      Yes, of course. BUT TESTING AND MODIFYING THE PROGRAMS TAKE RESOURCES. Resources cost money. This thread is about standardization and how it effects Perl. One of the effects of not having standardization is that incompatable changes happen more frequently, and worse, there's no "safe" area to program in - anything can change. This is a hurdle for corporations (and programmers). This will cause people and coorperations to not use Perl. That's how it effects Perl.

      Of course, if you don't supply the version of Perl your script is used with, you will need to test your script against all versions of Perl, but at least the future versions of Perl go through prereleases ("Release Candidates") before becoming public, and so you have some chance of getting an early warning by testing your program against bleadperl. Once again, testing only (hopefully) shows the program will break. It only shows resources have to be consumed to get the program working again. It won't fix them. Shipping the version of Perl required is all handy, but if your 5.005_03 program needs to start understanding Unicode, the program shall need to run under 5.6.0 or later. So added to the costs of adding new features to your program come the cost of finding and fixing any breakages.

      I never said it wasn't solvable. It is. But the thread is about the effects of non having a standard. And this is one of the effects. I am fully aware there are benefits of not having a standard. I'm not promoting Perl standardization. I'm not even saying it's unacceptable an upgrade of Perl breaks programs. All I am saying is "an upgrade of Perl causes program breakage - and here are some examples". Your reaction of "you're using the wrong Perls then" make as much sense as if you had said "cows can fly".

        Your reaction of "you're using the wrong Perls then" make as much sense as if you had said "cows can fly".

        I prefer to see my reaction of "you're using the wrong Perls then" more in the context of "There are Perls that you can upgrade between without worrying that your program breaks". And that is still the point of this thread.