Why doesn't this 'next if' work?

M

Max Moor

Hi All,

I'm fairly new to perl, and have already fixed this problem, but I
want to understand why it didn't work before.

This is the original, non-working code:

@o_list = ();
foreach my $o ( @{$stuff->{thingys}} ) {

# Exclude if no match
$match = 'n';
foreach $thingy (@test_thingys) {

if ($o->{thingy} == $thingy) {
$match = 'y';
last;
}
}
next if ($match != 'y');

push @o_list, $o;
}

Basically, its running through a list of "thingys", checking to see if
the item matches any of a list of test "thingys." Before checking the list,
I set $match to 'n'. If I find a match, I set it to 'y' and dump out of the
loop. At least, that was the intent. What really happened was that "next
if" line never ran, and all items got pushed onto "o_list." I did some
checking, and found that $match equaled 'n'. The line simply wasn't ever
running.

The working snippet...

@o_list = ();
foreach my $o ( @{$stuff->{thingys}} ) {

# Exclude if no match
$match = 0;
foreach $thingy (@test_thingys) {

if ($o->{thingy} == $thingy) {
$match = 1;
last;
}
}
next if (!match);

push @o_list, $o;
}

The only change was the "flag" values. Instead of 'y' and 'n', it's
now 0 and 1.

Can anyone tell me what about the 'n' and 'y' messed up the logic?

Thanks for your help,
Max
 
U

Uri Guttman

MM> next if ($match != 'y');

that does a numeric comparison. 'n' is 0 and so is 'y' so that will
never be true. use eq for string compares. if you had enabled warnings
perl would have told you this. also you aren't using strict which helps
too. ask perl for all the help it can give you.

now the bigger picture is you shouldn't be using boolean flags like that
in general. proper use of next/last will eliminate the need for them. i
don't have the time to review the logic but others may do so.

uri
 
M

Max Moor

MM> next if ($match != 'y');

that does a numeric comparison. 'n' is 0 and so is 'y' so that will
never be true. use eq for string compares. if you had enabled warnings
perl would have told you this. also you aren't using strict which helps
too. ask perl for all the help it can give you.

now the bigger picture is you shouldn't be using boolean flags like that
in general. proper use of next/last will eliminate the need for them. i
don't have the time to review the logic but others may do so.

uri

Hi uri,

Thanks for the answer. Makes sense.

I also agree with you about flags, but there's still alot of ugly in
this code. It's really just an eval block inside a larger perl script that
we users on a particular site are allowed access to. We can use it to
price check items we have for sale.

I'm a C programmer from way back, but haven't done perl before. I
started with the code as generated by an auto-writer they provide.
Hopefully I'll get to know my way around perl well enough that some things
like bad logic will get cleaned up.

I'll see what I can do to add warnings and strict-ness. I'm not sure
how that might affect the larger script I don't have say over.

Anyway, thanks again for the knowledge. I appreciate the help.

- Max
 
S

sln

Hi All,

I'm fairly new to perl, and have already fixed this problem, but I
want to understand why it didn't work before.

This is the original, non-working code:

@o_list = ();
foreach my $o ( @{$stuff->{thingys}} ) {

# Exclude if no match
$match = 'n';
foreach $thingy (@test_thingys) {

if ($o->{thingy} == $thingy) {

if .. == .. or .. eq ..
$match = 'y';
last;
}
}
next if ($match != 'y');

if .. != .. or .. ne ..
push @o_list, $o;
}

Take your pick. Not both.

-sln
 
D

Doug Miller

if .. == .. or .. eq ..

depending on the type of the two operands.
if .. != .. or .. ne ..

Wrong. ne is necessary for string comparisons.
Take your pick. Not both.

Nonsense. $match, being assigned values of either 'n' or 'y', clearly requires
the string inequality operator ne. He can't "take [his] pick" there.

Likewise, he can't pick and choose in the other comparison either. If the
operands are numeric, he *must* use ==; if they are strings, he *must* use eq.
 
S

sln

if .. == .. or .. eq ..

depending on the type of the two operands.
if .. != .. or .. ne ..

Wrong. ne is necessary for string comparisons.
Take your pick. Not both.

Nonsense. $match, being assigned values of either 'n' or 'y', clearly requires
the string inequality operator ne. He can't "take [his] pick" there.

Likewise, he can't pick and choose in the other comparison either. If the
operands are numeric, he *must* use ==; if they are strings, he *must* use eq.
^^^^^^^^^^^^^^^^^^^^^^^^^
Nonsense, 2 == ... and 2 eq ...

-sln
 
S

sln

Hi All,

I'm fairly new to perl, and have already fixed this problem, but I
want to understand why it didn't work before.

This is the original, non-working code:

@o_list = ();
foreach my $o ( @{$stuff->{thingys}} ) {

# Exclude if no match
$match = 'n';
foreach $thingy (@test_thingys) {

if ($o->{thingy} == $thingy) {

if .. == .. or .. eq ..

depending on the type of the two operands.
$match = 'y';
last;
}
}
next if ($match != 'y');

if .. != .. or .. ne ..

Wrong. ne is necessary for string comparisons.
push @o_list, $o;
}

Take your pick. Not both.

Nonsense. $match, being assigned values of either 'n' or 'y', clearly requires
the string inequality operator ne. He can't "take [his] pick" there.

Likewise, he can't pick and choose in the other comparison either. If the
operands are numeric, he *must* use ==; if they are strings, he *must* use eq.
^^^^^^^^^^^^^^^^^^^^^^^^^
Nonsense, 2 == ... and 2 eq ...

-sln

There should actually be a 2 e= ... operator, no need for conversion (if necessary).

-sln
 
S

sln

if .. == .. or .. eq ..

depending on the type of the two operands.
if .. != .. or .. ne ..

Wrong. ne is necessary for string comparisons.
Take your pick. Not both.

Nonsense. $match, being assigned values of either 'n' or 'y', clearly requires
the string inequality operator ne. He can't "take [his] pick" there.

Likewise, he can't pick and choose in the other comparison either. If the
operands are numeric, he *must* use ==; if they are strings, he *must* use eq.

But, match != 'y' is valid, isin't it? Isin't that valid???

-sln
 
J

Jürgen Exner

Likewise, he can't pick and choose in the other comparison either. If the
operands are numeric, he *must* use ==; if they are strings, he *must* use eq.

Actually you can mix and match. But you better know exactly what you are
doing.

There is nothing stopping you from comparing the string values of two
numbers and actually of the top my head I can't think of a scenario,
where you would get an unexpected surprise.

And you can also compare the numerical values of two strings. However in
this case you really better know what those numerical values are going
to be because most of the time it's probably not what you would expect.

jue
 
S

sln

Actually you can mix and match. But you better know exactly what you are
doing.

There is nothing stopping you from comparing the string values of two
numbers and actually of the top my head I can't think of a scenario,
where you would get an unexpected surprise.

And you can also compare the numerical values of two strings. However in
this case you really better know what those numerical values are going
to be because most of the time it's probably not what you would expect.

jue

Very well said.

-sln
 
D

Doug Miller

Actually you can mix and match. But you better know exactly what you are
doing.

There is nothing stopping you from comparing the string values of two
numbers

As long as you consider unexpected results to be "nothing".
and actually of the top my head I can't think of a scenario,
where you would get an unexpected surprise.

I can...

1 gt 02
-1 lt -2
1 ne 01
-0 ne 0
1 ne +1
+1 lt -1
8 ne 010
15 ne 0xF
0xF ne 0xf
And you can also compare the numerical values of two strings. However in
this case you really better know what those numerical values are going
to be because most of the time it's probably not what you would expect.

OK, perhaps I should have added "... if he plans on getting the results that a
naive failure to understand the difference would lead him to expect." <g>
 
S

sln

As long as you consider unexpected results to be "nothing".


I can...

1 gt 02
-1 lt -2
1 ne 01
-0 ne 0
1 ne +1
+1 lt -1
8 ne 010
15 ne 0xF
0xF ne 0xf

OK, perhaps I should have added "... if he plans on getting the results that a
naive failure to understand the difference would lead him to expect." <g>

But, but, the point is that its allowable, not necesarily always right.

-sln
 
S

sln

Quoth (e-mail address removed) (Doug Miller):

Only one of these gives a different result from a numerical comparison.
On systems that support IEEE floats, you can add

-0.0 ne 0

Of course, if you replace all those literal numbers with quoted strings,
they all compare different numerically, though in some cases this is
because they don't numify as you might expect.


Talking about comparing 'strings' and 'numbers' is incorrect in Perl.
The appropriate question is 'do you wish to compare string values or
numeric values?'.

Ben

Yeah, its a formulea, its undefined too, really, throw that in, but, whats in
a conversion, nobody wants to know, thats why its !defined $value instead of !$value.

-sln
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top