Forcing Array Context

P

Peter Kay

I want to pass in arguments to a subroutine via an array or list.
Seems simple enough, right? Well, no, because the array keeps getting
kicked into scalar context. An example perl script is provided:

Any thoughts?
Thanks,
--Peter

------------------------------

#!/usr/bin/perl -w
use strict;

sub do_it ($$@);

my @args=("a","b","c");

do_it( "a", "b", @args ); #works
do_it( @args ); # Doesn't work:
# Not enough arguments for main::do_it at g.pl line 9, near "@args )"
# Execution of test.pl aborted due to compilation errors.


sub do_it ($$@)
{
my ($a, $b, @c) = @_;
print("Loaded $a, $b, others of @c\n");
}
 
A

A. Sinan Unur

(e-mail address removed) (Peter Kay) wrote in
I want to pass in arguments to a subroutine via an array or list.
Seems simple enough, right? Well, no, because the array keeps getting
kicked into scalar context. An example perl script is provided:

Any thoughts?

I don't get it. You specify prototype and then complain when that prototype
is obeyed. Either the prototype is wrong or the way you call the sub.

....
#!/usr/bin/perl -w
use strict;

sub do_it ($$@);

my @args=("a","b","c");

Whitespace is not a scarce commodity.
do_it( "a", "b", @args ); #works
do_it( @args ); # Doesn't work:
# Not enough arguments for main::do_it at g.pl line 9, near "@args )"
# Execution of test.pl aborted due to compilation errors.

Actually, that is working. The fact that it does not do what you want is
immaterial.
 
P

Paul Lalli

I want to pass in arguments to a subroutine via an array or list.
Seems simple enough, right? Well, no, because the array keeps getting
kicked into scalar context. An example perl script is provided:

Any thoughts?
Thanks,
--Peter

------------------------------

#!/usr/bin/perl -w
use strict;

sub do_it ($$@);

my @args=("a","b","c");

do_it( "a", "b", @args ); #works
do_it( @args ); # Doesn't work:
# Not enough arguments for main::do_it at g.pl line 9, near "@args )"
# Execution of test.pl aborted due to compilation errors.


sub do_it ($$@)
{
my ($a, $b, @c) = @_;
print("Loaded $a, $b, others of @c\n");
}


You say you want to pass in parameters via an array, but you very
specifically define the subroutine to only allow two scalars followed by a
list. So is your description wrong, or do you just not understand why
you're using a prototype?

To put it another way - Perl's doing both exactly what it's supposed to
do, and exactly what you told it to. If that's not what you want, stop
telling it to do that.

Paul Lalli
 
R

Randal L. Schwartz

Peter> sub do_it ($$@);

Prototypes. Eliminate. Crush. Kill. Destroy.

Never use prototypes. Or at least, not until you understand
exactly why I say "never use prototypes". :)
 
E

Eric Schwartz

Peter> sub do_it ($$@);

Prototypes. Eliminate. Crush. Kill. Destroy.

Never use prototypes. Or at least, not until you understand
exactly why I say "never use prototypes". :)

I still have to train myself not to use them, after having decided
quite some time back that they were useful. I've since been convinced
otherwise, but I still have to remind myself that they're not doing
what I think they're doing.

-=Eric
 
P

Peter Kay

Peter> sub do_it ($$@);

Prototypes. Eliminate. Crush. Kill. Destroy.

Ok, ok, I get the idea!

I was naively hoping Perl would expand the list, push the first two
elements into the two scalars, and continue on its way. My bad.

Thanks all :)

--Peter
 
T

Tad McClellan

I was naively hoping Perl would expand the list, push the first two
elements into the two scalars, and continue on its way.


That is exactly what Perl would do if you would only
eliminate the prototype. :)
 
P

Peter Kay

Tim Hammerquist said:
Prototypes serve
a different purpose in Perl and are almost never necessary. Don't worry
abou them for now.

So what is the official purpose of prototypes in Perl? They certainly
forced me to make sure I passed in at least some elements ;-)

--Peter
 
P

Paul Lalli

So what is the official purpose of prototypes in Perl? They certainly
forced me to make sure I passed in at least some elements ;-)

I've only ever found two uses for prototypes:
1) To generate a compile-time error when you accidentally call a
subroutine "the wrong way".
2) To automatically create a reference an array passes as a parameter,
rather than allowing the array to 'flatten' along with the other
parameters into @_

Ex of 2:


#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

sub foo;
sub bar(\@\@);

my @let = qw/a b c/;
my @num = qw/1 2 3/;

foo(@let, @num);
bar(@let, @num);

sub foo {
#Here, we have:
# $_[0] = 'a';
# $_[1] = 'b';
# $_[2] = 'c';
# $_[3] = '1';
# $_[4] = '2';
# $_[5] = '3';
print Dumper(\@_);
}

sub bar (\@\@) {
#Here, we have:
# $_[0] = ['a', 'b', 'c'];
# $_[1] = ['1', '2', '3'];
print Dumper(\@_);
}

__END__

Paul Lalli
 
R

Randal L. Schwartz

Peter> So what is the official purpose of prototypes in Perl? They certainly
Peter> forced me to make sure I passed in at least some elements ;-)

It permits you to write weird subroutines that parse in the same manner
as some of the odder built-ins.
 
B

Brian McCauley

Randal said:
Peter> So what is the official purpose of prototypes in Perl? They certainly
Peter> forced me to make sure I passed in at least some elements ;-)

It permits you to write weird subroutines that parse in the same manner
as some of the odder built-ins.

Whilst this is strictly a spacial case of what Randal just said it's
probably worthy of a special mention that the explicitly empty prototype
allows things that parse like constants (indeed this is how the constant
pragma (now) works).

use constant FOO => 2;
print FOO + 2;

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
B

Brian McCauley

I want to pass in arguments to a subroutine via an array or list.
Seems simple enough, right? Well, no, because the array keeps getting
kicked into scalar context.

Other people have mentioned that you probably didn't want a prototype.

Nobody has mentioned that there is a special syntax of subrouitne call
that suppresses prototype handing.
sub do_it ($$@);

my @args=("a","b","c");

do_it( "a", "b", @args ); #works
do_it( @args ); # Doesn't work:

&do_it( @args ); # Works by supressing the prototype.

Note - I do not recommend you do this in your situation, I only mention
it for completenes since it is the answer to the question you asked as
opposed to the answer you actually needed :).

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top