in reply to Re^4: Prototype for constant items???
in thread Prototype for constant items???

The problem is, the scalar of an array IS just a plain old scalar. You can't expect to tell the difference between the size of an array (such as '3'), and a plain old number (such as '3'). And your function really shouldn't care how the caller came up with the parameter it passed you.

If you expect an integer from 1 to 5, and you are passed the scalar of an array that happens to have between 1 and 5 elements, that is hardly wrong. It may just be a fancy way of counting widgets.

use strict; use warnings; use Carp; use constant BAR => 3.14159265; my @list = ('p','i','e'); taster(BAR); taster(22/7); taster("constant"); taster(\@list); taster(@list); taster(scalar @list); sub taster { my $p1 = shift; carp "Hey, that's too many parameters!" if @_; print "Ref of $p1 is '".(ref $p1)."'\n"; }
Gives
Ref of 3.14159265 is '' Ref of 3.14285714285714 is '' Ref of constant is '' Ref of ARRAY(0x182af0c) is 'ARRAY' Hey, that's too many parameters! at test.pl line 18 main::taster('p', 'i', 'e') called at test.pl line 12 Ref of p is '' Ref of 3 is ''

Replies are listed 'Best First'.
Re^6: Prototype for constant items???
by LanX (Saint) on Sep 26, 2009 at 00:48 UTC
    You can't expect to tell the difference between the size of an array (such as '3'), and a plain old number (such as '3').

    Again: I can tell the difference between scalar and an array, but just not for constants.

    You're still missing the point ... I marked it for you, to make it clearer:

    DB<4> sub tst (\[$@]) { print ref $_[0] } DB<5> $a="a";@a=(1..3) DB<6> tst $a SCALAR DB<7> tst @a ARRAY DB<8> tst "a" # <--------- that's the point ! Type of arg 1 to main::tst must be one of [$@] (not constant item) at +(eval 12)[/usr/share/perl/5.10/perl5db.pl:638] line 2, at EOF

    Cheers Rolf

      The problem there, is that you are still using prototypes. I am saying; ditch that, and just check the parameters in the sub.

      If the caller wants to pass an array as the first parameter, they can throw a reference slash in front of it, or square brackets around it. If they want to pass a list of multiple parameters, they can just pop the ($alpha,@rgb) in there without your sub forcing it into just two parameters and then trying to untangle it later.

      My main point: Use prototypes if you want to mangle the caller's code. Use if croak, warn, etc if you want to do type and sanity checking.

      Note: If they pass an array where they should have passed an arrayRef, then you should croak with a detailed version of "Too Many Parameters!" and/or "Value out of range", where applicable.

      Come to think of it, it would be nice to have a template of:

      sub foo { my $failed; ($failed = 1 and carp "First Parameter must be greater than zero") i +f $_[0] <= 0; ($failed = 1 and carp "Too many parameters") if scalar @_ > 3; die "Invalid parameters; cannot continue" if $failed; ... }
      since that would print out all of the errors before stopping, rather than just one error per run.