Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
| Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
04-18-2005, 09:58 AM
|
#1
|
|
Member
Registered: Jul 2003
Location: CT, USA
Distribution: Debian Sarge (server), Etch (work/home)
Posts: 601
Rep:
|
perl: passing 2 individual arrays/lists as args
Suppose I'm writing a function that I want to operate on two different arrays:
Code:
#!/usr/bin/perl
use warnings;
use strict;
my @a = ( 1, 2, 3 );
my @b = qw/ foo bar /;
sub do_something_with_two_arrays
{
my (@a1, @a2) = @_; # ? XXX
print "In the first array arg passed, we have:\n";
for ( @a1 ) { print "$_\n"; }
print "And in the second array arg passed:\n";
for ( @a2 ) { print "$_\n"; }
# Maybe some processing follows...
}
print "-" x 40, "\n";
do_something_with_two_arrays @a, @b;
print "~" x 40, "\n";
do_something_with_two_arrays( @a, @b ); # Nope. Same as above.
print "=" x 40, "\n";
How does Perl know where the first array ends and the next one begins?
I'm looking at the docs for the built-in 'push' function. It says that operator takes an ARRAY and then also a LIST. What's the difference? How does push know where the first one ends and the next one begins?
|
|
|
|
04-18-2005, 10:05 AM
|
#2
|
|
Member
Registered: Jul 2003
Location: CT, USA
Distribution: Debian Sarge (server), Etch (work/home)
Posts: 601
Original Poster
Rep:
|
BTW, I realize that I can just use references to arrays to do what I want to do, however, I'd like to understand how builtins like 'push' do their magic.
|
|
|
|
04-18-2005, 11:51 AM
|
#3
|
|
Member
Registered: Mar 2004
Location: Massachusetts
Distribution: Debian
Posts: 557
Rep:
|
IIRC, you can do
Code:
sub foo (@@) {
my ($ref1, $ref2) = @_;
....
}
foo(@array1, @array2);
The only problem with this is that in some situations it's possible to compile the code which calls foo before compiling foo itself, in which case the calling code won't know about the (@@) business and so will just pass a flat array. Of course, the perl builtins are guaranteed to be compiled before any code that uses them.
|
|
|
|
04-18-2005, 12:53 PM
|
#4
|
|
Member
Registered: Sep 2004
Location: south texas
Distribution: fedora core 3,4; gentoo
Posts: 192
Rep:
|
perl doesn't know where one ends and the other begins. I believe the solution is to use references. the fact that perl throws all of it's subroutine arguments into one big list is handy most of the time, unless your dealing with arrays. So what you would do is create references to the arrays (kind of like pointers) and pass the references to the sub, then dereference them in the sub. for example:
Code:
#!/usr/bin/perl
use warnings;
use strict;
my @a = ( 1, 2, 3 );
my @b = qw/ foo bar /;
$a_ref = \@a;
$b_ref = \@b;
do_something_with_two_arrays($a_ref, $b_ref);
do_something_with_two_arrays($b_ref, $a_ref);
sub do_something_with_two_arrays
{
my ($a1_ref, $a2_ref) = @_;
print "In the first array arg passed, we have:\n";
for ( @$a1_ref ) { print "$_\n"; }
print "And in the second array arg passed:\n";
for ( @$a2_ref ) { print "$_\n"; }
# Maybe some processing follows...
}
the \ operator creates a reference, in this case to an array (@). a reference is a scalar data. to dereference a reference, just put the appropieate symbol in front of the reference name. e.i.
scalar: $$ref
array: @$ref
hash: %$ref
hope this helps
|
|
|
|
04-18-2005, 12:57 PM
|
#5
|
|
Member
Registered: Jul 2003
Location: CT, USA
Distribution: Debian Sarge (server), Etch (work/home)
Posts: 601
Original Poster
Rep:
|
Ahh... that (@@) function declaration notation seems to be what I was missing. I'll look further into it. Thanks.
|
|
|
|
04-18-2005, 01:20 PM
|
#6
|
|
Member
Registered: Jul 2003
Location: CT, USA
Distribution: Debian Sarge (server), Etch (work/home)
Posts: 601
Original Poster
Rep:
|
Thanks sirclif. I've also found "man perlreftut" and, of course, "man perlref" pretty helpful as well. 
|
|
|
|
04-18-2005, 01:27 PM
|
#7
|
|
Member
Registered: Sep 2004
Location: south texas
Distribution: fedora core 3,4; gentoo
Posts: 192
Rep:
|
sorry i didn't see your replay saying that you already knew about references. the built in function push takes an array and 'tacks on' a scalar value or a list to the end of the array. there isn't much difference between an array and a list. an array is just a list with a name really. anyhow, given an array array1 you can push and pop elements on and off.
@array1 = (1,2,3);
push @array1, 4;
array1 now looks like (1,2,3,4)
vise versa if you pop the array into a scalar
$tmp = pop @array1;
tmp is now 4. but again, push, pop, unshift, and shift have no idea that an array is supposed to be more than one array, they just add and remove elements from the back and front of an array.
|
|
|
|
04-18-2005, 02:05 PM
|
#8
|
|
Member
Registered: Jul 2003
Location: CT, USA
Distribution: Debian Sarge (server), Etch (work/home)
Posts: 601
Original Poster
Rep:
|
> but again, push, pop, unshift, and shift have no idea that an
> array is supposed to be more than one array, they just add
> and remove elements from the back and front of an array.
Yes, but there's magic going on there. "push", of course, *modifies* @array1. If the args passed to "push" were all simply flattened into one list, there would be no way for "push" to know about the array it was supposed to modify. This is why it seems (to me) like "(@@)" is key. Looks like "man perlsub" explains it under the heading "Prototypes" (which I'm currently having a look at :).
Thanks.
Last edited by johnMG; 04-18-2005 at 02:08 PM.
|
|
|
|
04-18-2005, 02:16 PM
|
#9
|
|
Member
Registered: Sep 2004
Location: south texas
Distribution: fedora core 3,4; gentoo
Posts: 192
Rep:
|
ah, i see what your saying. the builtin function push takes two arrays and still knows how to deal with it. buitins also do not require parentheses around thier arguments, or the & operator.
|
|
|
|
04-18-2005, 02:39 PM
|
#10
|
|
Member
Registered: Mar 2004
Location: Massachusetts
Distribution: Debian
Posts: 557
Rep:
|
Quote:
|
buitins also do not require parentheses around thier arguments, or the & operator.
|
Actually, user functions don't either : )
Code:
15:38 aluser@alf:~$ perl -e 'sub foo { print "hi there $_[0]\n" } foo "bob"'
hi there bob
|
|
|
|
04-18-2005, 03:12 PM
|
#11
|
|
Member
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Gentoo, Slackware
Posts: 217
Rep:
|
Quote:
|
Actually, user functions don't either : )
|
Not having to use the & operator is only true if the subroutine is defined before it is used.
|
|
|
|
04-18-2005, 03:13 PM
|
#12
|
|
Member
Registered: Sep 2004
Location: south texas
Distribution: fedora core 3,4; gentoo
Posts: 192
Rep:
|
wow, sure enought.
why can't i get it to work in a script file?
|
|
|
|
04-18-2005, 03:49 PM
|
#13
|
|
Member
Registered: Mar 2004
Location: Massachusetts
Distribution: Debian
Posts: 557
Rep:
|
Quote:
|
why can't i get it to work in a script file?
|
Evidently you do need the parenthesis if you have the declaration of the sub after its use. This works:
Code:
#!/usr/bin/perl
use strict;
use warnings;
foo("bob");
sub foo {
print "hi there $_[0]\n";
}
I'm not aware of any case where the & is required in a call to the function; I use it to take references and that's about it. Of course, it's a matter of style.
For user functions, I tend to always use parentheses; probably because I've had that error from not predeclaring the sub at some point and mostly because it makes things less clear not to have them.
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 10:39 AM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|