To make it default (but not globally so), I think you should be able to use overload 'eq' => \&equals_no_coerce;
Note that with your comparator, !(undef eq undef), which I'm not sure you want. Also, it's generally better to say "return" to return false, not "return 0". On Tue, May 17, 2011 at 12:43 PM, ynon perek <[email protected]> wrote: > Hi, > Regarding Javascript, I never forget the special === operator because I > have my vim configured to get mad when I use the other one. I also use some > automatic lint tools (jslint), which is like Perl::Critic only in JS that > checks using the non-coercing operator. > > I can see why undef eq "" is a feature, I just feel it's a wrong feature. > It should be the exception not the rule. Using fatal warnings helps in > finding and fixing, but not so much in preventing. (the hash was just an > example, coercion can be confusing in other places as well). > Just to be clear, I find it hard to think of a case where I actually had > encountered that warning, and left it in production code. The "use of > uninitialized value..." warning is almost always an indication for mistake. > > What I have in mind is something like this one (though I'm still not sure > how to make it the default): > > use strict; > use warnings; > > package NonCoercingString; > use subs qw/equals_no_coerce/; > > use Moose; > has 'data', is => 'ro', required => 1; > > use overload > 'eq' => \&equals_no_coerce, > 'ne' => sub { ! &equals_no_coerce }; > > sub equals_no_coerce { > my ($self, $other, $swap) = @_; > > defined ($self->data) || return 0; > defined ($other) || return 0; > > return $self->data eq $other; > } > > package main; > use Test::More 'no_plan'; > my $foo = NonCoercingString->new(data => ''); > > # these both pass - good > ok($foo eq ''); > ok($foo ne undef); > > # this one passes. Not so good > ok('' eq undef); > > > > > On 16 May 2011 13:16, Gaal Yahas <[email protected]> wrote: > >> Well, if you're worried you might forget checks, what would stop you from >> forgetting to use the special operator and using eq at some place? >> >> undef eq "" (with warning) is a feature of Perl. If you have a test suite, >> perhaps you can run it with Test::NoWarnings and look to maintain coverage. >> (In fact, maybe you want use warnings FATAL in your production code?) >> >> Another option is that when designing a data structure of particular >> importance, don't expose its native hash representation to users; force them >> to use some accessor interface over it instead and put assertions there. >> >> On Fri, May 13, 2011 at 1:02 AM, ynon perek <[email protected]> wrote: >> >>> Hi, >>> Obviously I do use the explicit notation, until that one time that I >>> forget ... For this program, the right solution includes yours *and* the >>> extra check on the dictionary. >>> Being more specific, these perl lines: >>> >>> die if ! exists $users{$username}; <---- I'd like to get rid of this >>> line >>> >>> if ( $users{$username} eq $password ) { >>> ... >>> } >>> >>> are pretty much this JS: >>> >>> if (users[username] === password) { >>> } >>> >>> The thing is, in JS I'm not afraid an underfined will turn out equal to >>> the empty string. (Well, I actually would fear it, if it wasn't for the >>> wonderful triple-equal operator). >>> >>> >>> On 13 May 2011 00:48, sawyer x <[email protected]> wrote: >>> >>>> >>>> On Thu, May 12, 2011 at 11:53 PM, ynon perek <[email protected]>wrote: >>>> >>>>> Hi, >>>>> Just found another one of them annoying bugs today - exemplified by the >>>>> code below. It's easy to see a non existent username will match an empty >>>>> password (silent conversion between undef and empty string). >>>>> Javascript has an explicit equality operator that does not coerce types >>>>> (called the ===). In perl, I usually check for undefs (until I forget). Is >>>>> there such an operator for perl ? >>>>> >>>> >>>> You can (and should) use more explicit notation: >>>> >>>> >>>> chomp( my $username = <> ); >>>> chomp( my $password = <> ); >>>> >>>> defined $username && defined $password >>>> or die "Missing username and password"; >>>> >>>> In a correct interface (if you're using web, this would be done in JS in >>>> the front, *and* in the back) you should be checking your input to make >>>> sure >>>> it was inserted correctly. >>>> >>>> >>>> _______________________________________________ >>>> Perl mailing list >>>> [email protected] >>>> http://mail.perl.org.il/mailman/listinfo/perl >>>> >>> >>> >>> _______________________________________________ >>> Perl mailing list >>> [email protected] >>> http://mail.perl.org.il/mailman/listinfo/perl >>> >> >> >> >> -- >> Gaal Yahas <[email protected]> >> http://gaal.livejournal.com/ >> >> _______________________________________________ >> Perl mailing list >> [email protected] >> http://mail.perl.org.il/mailman/listinfo/perl >> > > > _______________________________________________ > Perl mailing list > [email protected] > http://mail.perl.org.il/mailman/listinfo/perl > -- Gaal Yahas <[email protected]> http://gaal.livejournal.com/
_______________________________________________ Perl mailing list [email protected] http://mail.perl.org.il/mailman/listinfo/perl
