Re: Perl Bug (again)

2006-02-20 Thread D D Allen

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)

2006-02-20 Thread Chris Wagner
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)

2006-02-20 Thread DZ-Jay

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)

2006-02-18 Thread John Deighan

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)

2006-02-18 Thread Robert May
[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)

2006-02-17 Thread Chris Wagner
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)

2006-02-17 Thread Joe Discenza
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)

2006-02-17 Thread John Deighan

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)

2006-02-17 Thread John Deighan


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)

2006-02-17 Thread Robert May

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)

2006-02-17 Thread Chris Wagner
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)

2006-02-17 Thread Eric Amick
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)

2006-02-17 Thread Chris Wagner
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