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

Try the following two code snippets separately.
$vec = ''; vec($vec, 0, 4) = 1; $bits = unpack("b*", $vec); print "$bits\n"; -------- $vec = ''; my @params = (0, 4); vec($vec, @params) = 1; $bits = unpack("b*", $vec); print "$bits\n";

There's nothing in the vec documentation that says anything about requiring three separate and distinct parameters. Does anyone have any idea what's going on? Is there a better way of doing what I'm trying to do? (This is for an upgrade to Excel::Template, so I'd rather not require non-core modules, if possible.)

------
We are the carpenters and bricklayers of the Information Age.

Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Replies are listed 'Best First'.
Re: vec and array parameters
by Abigail-II (Bishop) on Jan 07, 2004 at 16:46 UTC
    vec isn't the only function that 'suffers' from this. Any function that does compile time checking of the number of arguments does so. Try the same with atan2 for instance.

    And a general piece of advice: to increase the changes someone actually answers your question, don't force them to cut and paste your code to see what it prints. Just include the output; that saves a lot of trouble for those who answer your query.

    Abigail

      Are there any plans / thoughts to fixing this 'problem'? Is it even considered a problem or is it just an annoyance?

      ------
      We are the carpenters and bricklayers of the Information Age.

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        It's just a result of perl's context coercive prototypes. You may consider it an annoyance if you like. The fix is Perl 6 :-)

        The only time this is mentioned as a problem is when people are discussing prototypes once a year. But then, people quickly agree that prototypes are a failed experiment, with only one or two somewhat useful cases, but it's too late to do it differently. I've never seen it be considered a real problem for primitives like vec. (More often than not, people will use the same third argument for vec, and use a constant).

        Abigail

Re: vec and array parameters
by duff (Parson) on Jan 07, 2004 at 16:53 UTC

    Well, there is some implication in the documentation because it does say: vec EXPR, OFFSET, BITS However, when in doubt, look at the prototype for the routine:

    perl -le 'print prototype "CORE::vec"'

    And you'll see that three arguments are required and that they are all coerced into a scalar context (assuming you understand perl's idea of prototypes :-)

    As for a work-around, that's easy:

    $vec = ''; my ($offset,$bits) = (0, 4); vec($vec, $offset, $bits) = 1; $bits = unpack("b*", $vec); print "$bits\n";
    :-)
Re: vec and array parameters
by davido (Cardinal) on Jan 07, 2004 at 17:21 UTC
    The prototype for vec is three scalars. See the following:

    use strict; use warnings; print prototype "CORE::vec"; print "\n"; __OUTPUT__ $$$

    Now try the same thing with a few other popular functions for which you can use either an array or a literal list as the 2nd (and subsequent) argument(s).

    use strict; use warnings; print prototype "CORE::push", "\n"; print prototype "CORE::sprintf", "\n"; print prototype "CORE::pack", "\n"; __OUTPUT__ \@@ $@ $@

    The difference is immediately apparent.

    See perldoc -f prototype for an explanation of how to use the prototype function to gain a better understanding of the prototypes of Perl internal "core" functions.


    Dave

Re: vec and array parameters
by Roy Johnson (Monsignor) on Jan 07, 2004 at 17:05 UTC
    I ran into the same thing with seek when writing this poem. If there is a reason you have an array instead of two separate variables for OFFSET and BITS, and you're going to call it a lot, you can write a wrapper like I did:
    sub my_vec { vec($_[0],$_[1],$_[2] }
    or just call it like vec($vec, $params[0], $params[1]).

    The PerlMonk tr/// Advocate
      I thought of that too, but if you try to use my_vec on the left side of an assignment, you get:
      Can't modify non-lvalue subroutine call at testvec.pl line 10.

        Oh, then just make your sub an lvalue sub like so:

        sub my_vec : lvalue { vec($_[0],$_[1],$_[2]) }

        Caveat scriptor, I didn't test this at all and I'm sure you need a modernish perl for it to work.

Re: vec and array parameters
by ambrus (Abbot) on Jan 09, 2004 at 12:10 UTC