duelafn has asked for the wisdom of the Perl Monks concerning the following question:

Good Day, I'm working on a Module for working with permutation groups. I always use strict, warnings, and I even write (and run) test scripts while I write the module! I am completely confused by this problem though. I have the following test script:
use strict; use warnings; use Group::Permutation; my $x = new Group::Permutation qw(1 3 2 4); print "x = $x\n"; print 'x of 2 = ',$x->of(2),"\n"; print 'ref of x of 2: ', ref $x->of(2),"\n"; print "x of 2 is three!\n" if ($x->of(2) == 3);
This produces the output:
x = (1, 3, 2, 4) x of 2 = 3 ref of x of 2:
Most notably, the test ($x->of(2) == 3) fails. I can't figure out why this happens.

The ref test was put in because I overloaded == and I wanted to make sure perl wasn't calling the wrong == (I also added a print statement to the == code).

For complete disclosure of information:
sub of { my $x = shift; my @y = map { $_-1 if defined && /^\d+$/ && $_>0 } @_; # protect the caller from placement errors return undef unless ($#y == $#_); return map { ($_<$$x{'n'}) ? $$x{'perm'}[$_] + 1 : $_+1 } @y; }
and
sub new { # SNIP # BEGIN vicious error checking # all input must be legitimate $x{'perm'}=[ map { $_-1 if defined and /^\d+$/ and $_ > 0} @_ ]; return undef unless $#{$x{'perm'}} == $#_; # it must really be a permutation of 0..n-1 return undef unless join(' ',sort { $a <=> $b } @{$x{'perm'}}) eq +join(' ',0..$#{$x{'perm'}}); # END error checking # SNIP $x{'n'} = scalar @{$x{'perm'}}; # for clarity in other places bless \%x, $class; }
The snipped sections are just some definitions and option parsing.

Thanks,

    -Dean

Replies are listed 'Best First'.
Re: (x == 3 && x != 3)
by no_slogan (Deacon) on Mar 11, 2002 at 22:22 UTC
    Sub of is returning a list into a scalar context. That gives you the length of the list, not the first element as you seem to want.

    Also, @y = map { $_-1 if mumble } @_ gives you a list that contains undefs where mumble is false. That means $#y is always equal to $#_.

    Update: Thanks for the correction, Randal. I had to read it a couple of times, but you're exactly right, of course.

      Sub of is returning a list into a scalar context. That gives you the length of the list, not the first element as you seem to want.
      There's no such thing as "returning a list into a scalar context". It's that sort of sloppy language that perpetuates the myth that such a beast can exist. What's actually happening is that you're using map in a scalar context, which counts the number of result elements, and returns that count. At no point was it ever just a list. "map in a scalar context" could be defined instead as "invoke nethack".

      -- Randal L. Schwartz, Perl hacker

      Ah yes, I am quite foolish. (hangs his head in shame -- it is sad what silly things get missed)

      Thanks also for the map warning, I'll fix that too.

      Thanks
          -Dean
Re: (x == 3 && x != 3)
by erikharrison (Deacon) on Mar 11, 2002 at 20:36 UTC

    I don't know about operator overloading, but it seems that $x->of(2) indeed returns 3 (as your print test shows). I suggest that you tell us how you've overloaded the == operator. Also, I'd step through the Perl debugger and find out exactly what is happening inside that last conditional.

    Cheers,
    Erik
Re: (x == 3 && x != 3)
by duelafn (Parson) on Mar 11, 2002 at 21:52 UTC
    Sorry, the == that should be (and is) used in the comparison of $x->of(2) and 3 is the default perl numerical comparison.

    Sorry for the confusion Erik.

    -Dean