Re: Perl Bug (again)
You're not necessarily wrong... or right. As indicated by many of the responses, you've used a Perl construct that is an edge condition in the language whose behavior isn't well defined. But it's also a dubious programming construct in any language. Translating that statement to english, conditionally define two variables, nextID and maxID and set their initial values to the first to elements of the array referenced by L IF L is true (defined and contains a non-zero value). So if L is false, then nextID and maxID are not defined, let alone initialized -- which makes it difficult/questionable to use those variables in subsequent lines of code -- regardless of the programming language. And I agree, use warnings should generate a warning message for conditional variable definitions. In Perl Best Practices by Damian Conway, well worth reading by beginning and veteran Perl programmers alike (and likely a bigger mental struggle for veteran Perl programmers challenged to change ingrained behaviors / Pearl programming styles), Chapter 6 on control structures starts with use block if, not postfix if. In this case, rewritting your problematic statement as a block if clarifies the problem and eliminates the undefined behavior. if ($L) { my ($nextID, $maxID) = @$L; } It then becomes obvious that the statement actually accomplishes nothing as $nextID and $maxID are only defined within the scope of the if block. Once the if block is closed (executed), $nextID and $maxID go out of scope / are no longer defined and therefore can't be used in subsequent statements. And if you attempted to use $nextID or $maxID in subsequent statements after the closing if brace, use strict would generate a fatal compile time error stating that $nextID and $maxID are undefined. And yes, as my ($nextID, $maxID) = @$L if $L; and the above are equivalent, they should produce equivalent Perl behaviors -- but they don't -- which arguably is a language flaw. And yes, Perl has its flaws. So read Perl Best Practices, I did. And consider the following paragraphs from the white paper A Box, Darkly: Obfuscation, Weird Languages, and Code Aesthetics by Michael Mateas and Nick Monfort. Full text available at http://nickm.com/cis/a_box_darkly.pdf. A fun read for those who There is also an Obfuscated Perl contest, run annually by The Perl Journal since 1996. While Perl is quite unlike C, even beginning Perl programmers will be quick to realize the great potential for obfuscation that lies within the language. For one thing, Perl offers a dazzling variety of extremely useful special variables, represented with pairs of punctuation marks; this feature of the language nearly merits an obfuscation category of its own. Perls powerful pattern-matching abilities also enable cryptic and deft string manipulations. Perl is sometimes deacronymized as Practical Extraction and Report Language, but has also been said to stand for Pathologically Eclectic Rubbish Lister. The language is ideal for text processing, which means that printing hello, world! and other short messages can be done in even more interesting ways. Thus, the tradition of writing an obfuscated Perl program that prints Just another Perl hacker, arose on USENET and became common enough that a program to do this is known simply as a JAPH. The popularity of these programs is attested to by the first section of the Perl FAQ, which answers the question What is a JAPH? [10] More generally, Perl has as its mantra there are many ways to do it. A half-dozen Perl programmers may easily know eight or ten different ways to code exactly the same thing. Because of this, obscure ways of doing fairly common tasks are lurking everywhere. A common, high-level obfuscation technique that is seen in obfuscated Perl and also in obfuscated C (however differently it may be expressed there) involves choosing the least likely way to do it. This could mean using a strange operator, a strange special variable, or an unusual function (or an ordinary function in an unusual way). It could also involve treating data that is typically seen as being one type as some other type, a view that is permissible according to the language but not intuitive. And then try to explain these lines -- why the first produces the output 10 and the second produces the output 30 -- which is not a Perl bug. print (5*2)*3; print \n; print 5*(2*3); print \n; Regards, ... Dewey John Deighan [EMAIL PROTECTED] Sent by: [EMAIL PROTECTED] 02/17/2006 02:28 PM To perl-win32-users@listserv.ActiveState.com cc Subject Re: Perl Bug (again) At 01:29 PM 2/17/2006, Chris Wagner wrote: At 12:46 PM 2/17/2006 -0500, John Deighan wrote: OK, same caveat as before - apparent bugs in Perl are usually user errors, but once again, I'm stumped. Here is my code. The problem I have is in the second call to getCached(), specifically, the line: my($nextID,$maxID) = @$L if $L; I think this is the error. Notice the if part
Re: Perl Bug (again)
At 09:50 AM 2/20/2006 -0500, D D Allen wrote: And then try to explain these lines -- why the first produces the output 10 and the second produces the output 30 -- which is not a Perl bug. print (5*2)*3; print \n; print 5*(2*3); print \n; Yep I've gotten burned several times with that caveat. I now have a name for it, parenthesis appropriation. -- REMEMBER THE WORLD TRADE CENTER ---= WTC 911 =-- ...ne cede malis 0100 ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Perl Bug (again)
At 09:50 AM 2/20/2006 -0500, D D Allen wrote: And then try to explain these lines -- why the first produces the output 10 and the second produces the output 30 -- which is not a Perl bug. print (5*2)*3; print \n; print 5*(2*3); print \n; As Larry Wall says in the Camel book: If it looks like a function, Perl will treat it as such. So, in the first line, Perl sees first: print (5*2) which very much looks like a function call (i.e. function name followed by arguments within parenthesis). It then interprets the line as the return value of that print function call (which will be 1 if it succeeded) multiplied by 3. But this is like saying: 10*3; on a statement by itself, which is useless, and so it is thrown away. It still prints the multiplication of 5*2, though, because that's what print does. However, this is most likely not what you wanted. If you enable warnings, you'll know immediately that something is wrong, as the compiler would complain with: print (...) interpreted as function Useless use of multiplication (*) in void context The third line is interpreted as you would expect because, it doesn't look like a function, so the stuff that follows print is taken as the full parameter to it: the multiplication is performed, and the output submitted to the print() function. To avoid this, it is usually a good idea to just wrap all function parameters around parenthesis when there could be doubt as to what are the actual parameters to it. So if you would have said: print ((5*2)*3); there wouldn't be any problem. Note that this is not a Perl bug, but a nuance of the flexibility of the language and its syntactic sugar. Other languages avoid these ambiguities by forcing you to use parenthesis on all function calls, all the time. But then everything will look like computer code, instead of the nice and fluid, human legible syntax that is achievable when writing good Perl. dZ. ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: [aswin32] RE: Perl Bug (again)
At 04:50 PM 2/17/2006, Robert May wrote: my is a compile time directive that creates the lexically scoped $i, giving is scope from its definition until the end of the enclosing block. Assignment is a run time operation. In your example the modified assignment doesn't get executed, so the value of $i is *not defined*, in current perl's it happens to take the 'undef' value. quote NOTE: The behaviour of a my statement modified with a statement modifier conditional or loop construct (e.g. my $x if ...) is undefined. The value of the my variable may be undef, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons. /quote OK, this was an excellent explanation of what is going on, so now I understand it and can thus avoid it. Still, we have the following situation: A construct in the language which is syntactically valid has an undefined behaviour. And, I admit, if I had read all of the voluminous Perl documentation, I would have eventually come across that fact. Furthermore, that construct has a behaviour that should never occur in a programming language, namely, a variable local to a function retains its value across invocations of that function. I might further point out that with both use strict and use warnings, there is no indication that I've used a bad construct in the code. When I execute with use strict and use warnings, there are some warnings, but only having to do with use of uninitialized values in '==' comparisons and '.' operators. When we have a construct that is easily detected by the compiler, and has an undefined result, with warnings in the documentation about its use - how can there not be a warning generated? ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: [aswin32] RE: Perl Bug (again)
[snip ... why doesn't my $i if 0; generate a warning under use warnings;] Glenn Linderman wrote: Partly because the behaviour was probably implemented unintentionally (hence no original warning or error), and has been treated (once discovered by those nefarious end-user types) as a feature in some code. Adding a warning then makes existing code noisier than it was, so the feature can only be added to blead not maint (if you are familiar with Perl development terminology). I _think_ I recall seeing comments on p5p that there is now a warning for that construct in blead? At least it was discussed. Try downloading Perl 5.9.x and see, if you really want to be sure. Anyway, it is currently a known gotcha... there is no other programming language that I am aware of that even allows such syntax, to conditionally declare variables, so it is surprising that you even attempted such... which has kept this from being a bigger problem than it would be otherwise. A (deprecated) warning was added in 5.9.1 according to this p5p summary: http://www.nntp.perl.org/group/perl.perl5.summary/98 quote Rafael noted also that the regression tests produce lots of warnings Deprecated use of my() in conditional, referring to the dubious and now deprecated construct my $foo = $bar if $quux; So the warning is maybe too noisy (although it indicates a bug waiting to happen.) Rafael and Dave Mitchell proposed some alternatives, but the current form of the warning is likely to go into 5.9.1, even if it's made lighter afterwards. /quote I has been discussed on p5p more recently (in the last few months) but I can't quickly turn p a reference. Regards, Rob. -- Robert May Win32::GUI, a perl extension for native Win32 applications http://perl-win32-gui.sourceforge.net/ ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Perl Bug (again)
At 12:46 PM 2/17/2006 -0500, John Deighan wrote: OK, same caveat as before - apparent bugs in Perl are usually user errors, but once again, I'm stumped. Here is my code. The problem I have is in the second call to getCached(), specifically, the line: my($nextID,$maxID) = @$L if $L; I think this is the error. Notice the if part. If $L is undefined, nothing before the if takes place, including the my declaration. Put the my's up by themselves and all works as expected. You always have to be careful in strining too many shortcuts together. -- REMEMBER THE WORLD TRADE CENTER ---= WTC 911 =-- ...ne cede malis 0100 ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Perl Bug (again)
Title: RE: Perl Bug (again) John Deighan wrote, on Fri 17-Feb-06 12:46 : my($nextID,$maxID) = @$L if $L; : : The parameter to getCached, $Customer, has a different value than : during the first call. Because of that, the variable $L is undefined. : What I expect the statement above to do is to create 2 new variables, : $nextID and $maxID. Then, if $L has a true value in it, it's treated : as a reference to a list and the first 2 values in that list would be : assigned to the variables. However, if $L is false, then the : variables would be left undefined. What's really blowing my mind is : the that values in $nextID and $maxID get the values THAT THEY WERE : ASSIGNED DURING THE PREVIOUS CALL TO THIS FUNCTION. Wow! They're my : variables inside the getCached() function. How could they end up with : values from a previous invocation of the function? Fascinating! You have one misconception right off: The my line is never executed (not even to make the new variables) if $L is false. Now I'm starting to speculate: Since your my variables aren't created the second time, the ones from the first time weren't destroyed, and those are the ones picked up (with their old values). Make the code my ($nextID, $maxID); ($nextID, $maxID) = @$L if $L; and see if that doesn't fix it. Good luck, Joe == Joseph P. Discenza, Sr. Programmer/Analyst mailto:[EMAIL PROTECTED] Carleton Inc. http://www.carletoninc.com 574.243.6040 ext. 300 fax: 574.243.6060 Providing Financial Solutions and Compliance for over 30 Years -Original Message- From: [EMAIL PROTECTED] on behalf ofTo: perl-win32-users@listserv.ActiveState.com; Lewis Foster; [EMAIL PROTECTED]; Todd Thurheimer; Chris Cain Subject: Perl Bug (again) OK, same caveat as before - apparent bugs in Perl are usually user errors, but once again, I'm stumped. Here is my code. The problem I have is in the second call to getCached(), specifically, the line: I've added the output from when I run this below. BTW, I'm running ActiveState ActivePerl v. 5.8.7 Build 815 under MS Windows 2000 Server. # --- use strict; our $hCache = {}; my $id1 = getCached('x'); my $id2 = getCached('y'); print(id1 = '$id1\n); print(id2 = '$id2\n); # --- sub getCached { my($Customer) = @_; my $L = $hCache-{$Customer}; print(defined($L) ? L defined\n:L undefined\n); my($nextID,$maxID) = @$L if $L; print(nextID = '$nextID', maxID = '$maxID'\n); if ($nextID==$maxID) { ($nextID,$maxID) = getNextMax($Customer); $hCache-{$Customer} = [$nextID+1, $maxID]; } else { ++$hCache-{$Customer}-[0]; } return $nextID; } # getCached() # --- sub getNextMax { my($CustomerName) = @_; if ($CustomerName eq 'x') { return (100,150); } elsif ($CustomerName eq 'y') { return (200,250); } } # getNextMax() # --- OUTPUT: # --- C:\ScriptstestIDs.pl L undefined nextID = '', maxID = '' L undefined nextID = '100', maxID = '150' id1 = '100 id2 = '100 ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Perl Bug (again)
At 01:29 PM 2/17/2006, Chris Wagner wrote: At 12:46 PM 2/17/2006 -0500, John Deighan wrote: OK, same caveat as before - apparent bugs in Perl are usually user errors, but once again, I'm stumped. Here is my code. The problem I have is in the second call to getCached(), specifically, the line: my($nextID,$maxID) = @$L if $L; I think this is the error. Notice the if part. If $L is undefined, nothing before the if takes place, including the my declaration. Put the my's up by themselves and all works as expected. You always have to be careful in strining too many shortcuts together. That in no way explains where the values that end up in those variables come from. Also, see my other post about the creation of the lexical variables in statement like my $var = expr if condition. If I'm wrong in that post, I'd like to know why. ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Perl Bug (again)
At 01:06 PM 2/17/2006, Joe Discenza wrote: Fascinating! You have one misconception right off: The my line is never executed (not even to make the new variables) if $L is false. OK, then, consider this program. Notice that there's a global $i which has the value 5. Now, when func() is called, if the my $i did not create a new lexically scoped variable, then the print line would print i = 5. But it doesn't - obviously because the lexical variable was created, but is undefined because $b is false. our $i = 5; our $b = 0; func(); sub func { my $i = 3 if $b; print(i = $i\n); } ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: [aswin32] RE: Perl Bug (again)
John Deighan wrote: At 01:06 PM 2/17/2006, Joe Discenza wrote: Fascinating! You have one misconception right off: The my line is never executed (not even to make the new variables) if $L is false. OK, then, consider this program. Notice that there's a global $i which has the value 5. Now, when func() is called, if the my $i did not create a new lexically scoped variable, then the print line would print i = 5. But it doesn't - obviously because the lexical variable was created, but is undefined because $b is false. our $i = 5; our $b = 0; func(); sub func { my $i = 3 if $b; print(i = $i\n); } my is a compile time directive that creates the lexically scoped $i, giving is scope from its definition until the end of the enclosing block. Assignment is a run time operation. In your example the modified assignment doesn't get executed, so the value of $i is *not defined*, in current perl's it happens to take the 'undef' value. In the original OPs question he had the modified assignment inside a loop. persyn says this at the end of the 'Statement modifiers' section: quote NOTE: The behaviour of a my statement modified with a statement modifier conditional or loop construct (e.g. my $x if ...) is undefined. The value of the my variable may be undef, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons. /quote So, ensure you separate the my $i and the modified assignment to ensure you know what's happening: my $i; $i = 3 if $b; Regards, Rob. ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Perl Bug (again)
At 02:28 PM 2/17/2006 -0500, John Deighan wrote: That in no way explains where the values that end up in those variables come from. Also, see my other post about the creation of the lexical variables in statement like my $var = expr if condition. If I'm wrong in that post, I'd like to know why. They get their value in the if ($nextID==$maxID) block. That evaluates to 0==0, true. Then ($nextID,$maxID) = getNextMax($Customer); assigns them their values. Now on the second pass to if ($nextID==$maxID) it's 100==150 which is false and they never get new values. -- REMEMBER THE WORLD TRADE CENTER ---= WTC 911 =-- ...ne cede malis 0100 ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Perl Bug (again)
On Fri, 17 Feb 2006 12:05:08 -0800, you wrote: OK, then, consider this program. Notice that there's a global $i which has the value 5. Now, when func() is called, if the my $i did not create a new lexically scoped variable, then the print line would print i = 5. But it doesn't - obviously because the lexical variable was created, but is undefined because $b is false. our $i = 5; our $b = 0; func(); sub func { my $i = 3 if $b; print(i = $i\n); } If you look in perldoc perlsub, you'll see the section on my() variables specifically mentions that putting statement modifiers on my() has undefined results, so all of this discussion is moot. -- Eric Amick Columbia, MD ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Perl Bug (again)
John Deighan wrote: OK, then, consider this program. Notice that there's a global $i which has the value 5. Now, when func() is called, if the my $i did not create a new lexically scoped variable, then the print line would print i = 5. But it doesn't - obviously because the lexical variable was created, but is undefined because $b is false. our $i = 5; our $b = 0; func(); sub func { my $i = 3 if $b; print(i = $i\n); } Here's a modification of that that illustrates the problem: $i = 5; func(); print(1: i = $i\n); func(); print(2: i = $i\n); sub func { print(before my: i = $i\n); my($i) = 3 if undef; print(after my: i = $i\n); $i = 7; print(after =: i = $i\n); } before my: i = 5 after my: i = after =: i = 7 1: i = 5 before my: i = 5 after my: i = 7 after =: i = 7 2: i = 5 So u see, it's after u utilize the my twice that things veer off into the twilight zone. I believe this is another side effect of the not fully developed closure syntax. The my statement is only partially doing it's thing. The $i=7 value should have gone out of scope when func returned but it didn't, it stayed alive after the indeterminate my. U have this thing for excessivly convoluted code. ;) -- REMEMBER THE WORLD TRADE CENTER ---= WTC 911 =-- ...ne cede malis 0100 ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs