(Ovid) Re: comparing two values under 'perl -w'
by Ovid (Cardinal) on Apr 02, 2002 at 16:02 UTC
|
There are several ways to solve this. One is to turn off warnings within the scope in which you have defined the variables. The following solution should work under most versions of Perl. It should also match your requirement that undef match undef.
use strict;
use warnings;
my ($w, $x, $y, $z)=(undef,undef,7,7);
if ( equal( $x, $y ) ) {
print "Equal\n";
} else {
print "Not equal\n";
}
if ( equal( $w, $x ) ) {
print "Equal\n";
} else {
print "Not equal\n";
}
if ( equal( $y, $z ) ) {
print "Equal\n";
} else {
print "Not equal\n";
}
sub equal {
my ( $first, $second ) = @_;
local $^W; # < 5.6
no warnings; # >= 5.6
return $first == $second;
}
Of course, I've encapsulated that in a sub to minimize its effects.
Cheers,
Ovid
Update: Fixed code per some pointers by VSarkiss.
Join the Perlmonks Setiathome Group or just click on the the link and check out our stats. | [reply] [d/l] |
Re: comparing two values under 'perl -w'
by demerphq (Chancellor) on Apr 02, 2002 at 16:12 UTC
|
Shouldnt use $a and $b as they can have bizzare side. And i have no idea if this is more or less elegant than yours... (IMO its easier to understand, but then again I like ternary ops.)
my $equal=defined($x) && defined($y) ? $x==$y : !defined($x) && !defin
+ed($y) ? 1 : 0;
Yves / DeMerphq
---
Writing a good benchmark isnt as easy as it might look. | [reply] [d/l] |
|
if(defined($x) && defined($y) ? $x==$y : !defined($x) && !defined($y))
+ {
| [reply] [d/l] |
|
| [reply] |
Re: comparing two values under 'perl -w'
by TheDamian (Priest) on Apr 02, 2002 at 22:53 UTC
|
Not that it solves your immediate problem (well, not in a practical timeframe anyway), but Perl 6 will have a much easier way to handle this kind of comparison:
$x =~ $y
From the latest Exegesis (which is now finished and coming RSN to a perl.com near you):
The humble Perl 5 "match a string against a regex" operator is promoted
in Perl 6 to a "smart-match an anything against an anything" operator. So now:
if ($val1 =~ $val2) {...}
works out the most appropriate way to compare its two scalar operands and does so. The result might be a numeric comparison ($val1 == $val2) or a string comparison ($val1 eq $val2) or a subroutine call ($val1.($val2))
or a pattern match ($val1 =~ /$val2/) or whatever else makes the most
sense for the actual run-time types of the two operands.
This new turbo-charged "smart match" operator will also work on arrays and hashes and lists:
if @array =~ $elem {...} # true if @array contains $elem
if $key =~ %hash {...} # true if %hash{$key}
if $value =~ (1..10) {...} # true if $value is in the list
if $value =~ ('a',/\s/,7) {...} # true if $value is eq to 'a'
# or if $value contains whitespa
+ce
# or if $value is == to 7
That final example illustrates some of the extra intelligence that Perl 6's =~ has: when one of its arguments is a list (not an array), the "smart match" operator recursively "smart matches" each element
and ORs the results together, short-circuiting if possible.
Larry hasn't said so explicitly, but I'm pretty sure that two undefs will also compare equal (silently) under the new =~.
| [reply] [d/l] [select] |
|
Thank you for the peek into the upcoming Exegesis. I eagerly look forward to spend another hour reading and dreaming for the best Perl ever :))
But I wanted to note that equalness of two undefs is very useful but contradicts with generally accepted laws of three-state logic, does it not?
| [reply] |
|
Thank you for the peek into the upcoming Exegesis.
...which is now fully on-line.
But I wanted to note that equalness of two undefs is very useful but contradicts with generally accepted laws of three-state logic, does it not?
It sure does. There was a long discussion around that issue on the perl6-language mailing list...starting here.
As I recall, there wasn't a clear outcome to the debate (surprise, surprise), but at the time Larry didn't seem keen on undef taking on the tri-state semantics of NULL.
| [reply] [d/l] |
Re: comparing two values under 'perl -w'
by particle (Vicar) on Apr 02, 2002 at 15:43 UTC
|
( defined $a and defined $b and $a == $b )
and and or are the same as && and ||, except their precedence is much lower.
don't use $a and $b. they're for sort
~Particle ;Þ
| [reply] [d/l] [select] |
|
This one misses the point that two undefs should turn out as equal.
| [reply] |
|
| [reply] |
Re: comparing two values under 'perl -w'
by Biker (Priest) on Apr 02, 2002 at 15:55 UTC
|
With all due respect, kappa.
When you aim to violate the underlying logic, you end up with code like that. You already state that NULL is not equal to NULL. This is also true for undefined; undefined is not equal to undefined.
If you force it to be that way, so be it. But Perl wasn't really written with that in mind, so it will be difficult to make your code elegant.
Everything went worng, just as foreseen.
| [reply] |
|
~% perl -we 'print "Really???\n" if undef == undef;'
+
Use of uninitialized value at -e line 1.
Use of uninitialized value at -e line 1.
Really???
~%
I know that undef in numerical context is just 0, but... | [reply] [d/l] |
|
| [reply] |
Re: comparing two values under 'perl -w'
by RMGir (Prior) on Apr 02, 2002 at 15:50 UTC
|
Interesting... Offhand, I can't think of anything, so I'd suggest:
sub equalOrBothNull
{
my ($a, $b) = @_;
((defined($a) && defined($b) && $a==$b) ||
(!defined($a) && !defined($b));
}
That way, you can at least hide the problem and make the main code more readable.
By the way, I'm pretty sure
not defined($a) && not defined($b)
is not what you want.
$ perl -MO=Deparse -e'not defined($a) && not defined($b)'
not defined $a && !defined($b);
-e syntax OK
Not doesn't bind as tightly as !.
--
Mike | [reply] [d/l] [select] |
Re: comparing two values under 'perl -w'
by Rhose (Priest) on Apr 02, 2002 at 16:38 UTC
|
How about creating a sub to do this?
#!/usr/bin/perl -w
use strict;
sub SpecialEqual
{
my $pVal1 = shift;
my $pVal2 = shift;
return 1 unless (defined $pVal1 or defined $pVal2);
return (defined $pVal1 and defined $pVal2 and $pVal1 == $pVal2);
}
print 'Testing: 1,1 = ',SpecialEqual(1,1),"\n";
print 'Testing: 1,2 = ',SpecialEqual(1,2),"\n";
print 'Testing: 2,1 = ',SpecialEqual(2,1),"\n";
print 'Testing: 2,2 = ',SpecialEqual(2,2),"\n";
print 'Testing: 2,2.5 = ',SpecialEqual(2,2.5),"\n";
print 'Testing: 2.5,2 = ',SpecialEqual(2.5,2),"\n";
print 'Testing: 2.5,2.5 = ',SpecialEqual(2.5,2.5),"\n";
print 'Testing: undef,1 = ',SpecialEqual(undef,1),"\n";
print 'Testing: 1,undef = ',SpecialEqual(1,undef),"\n";
print 'Testing: undef,undef = ',SpecialEqual(undef,undef),"\n";
Update:
Maybe I should have read RMGir's reply, yes? *Smiles*
| [reply] [d/l] |
|
I like this best of all :)
I works (good) and is readable (even more good). The one with ternary operator is shorter, thank you demerphq, but is a little too complicated to my taste. I like ?: myself, but not when they're nested. This code will probably be read by different people including perl novices.
| [reply] |
|
Er, I take minor issue with the term "nested". I too tend to avoid nested ternary ops but I generally think of the above example as "chained" and not nested.
my $x=$y ? $z ? $t : $u : $v; #nested
my $x=!$y ? $v : $z ? $t : $u; #chained
Oh and I dont really understand why people are so superstitious about ternary ops. Many non developers are even familiar with them as they come up often in excel cell formula if(Condtion,yesresult,noresult). OTOH if you have maintainence issues to consider then whatever minimizes headaches...
:-)
Yves / DeMerphq
---
Writing a good benchmark isnt as easy as it might look. | [reply] [d/l] |
|
Re: comparing two values under 'perl -w'
by gav^ (Curate) on Apr 02, 2002 at 15:53 UTC
|
if (!(defined $a && defined $b) || $a eq $b) {
print "equal";
}
gav^ | [reply] [d/l] |
|
What if $a = undef and $b = 3?
We get equal?
| [reply] [d/l] [select] |
Re: comparing two values under 'perl -w'
by I0 (Priest) on Apr 03, 2002 at 04:01 UTC
|
(not defined($a) && not defined($b)) || ($a == $b) | [reply] [d/l] |
|
| [reply] |