How to pass 2D array to sub function and return 2D array?

D

Davy

Hi all,

I want to pass 2D array to sub function and return 2D array.

//--------------------------
For example,
use strict;
use warnings;
my @array=([1,2,3],[4,5,6],[7,8,9]);
my $array_ref = \@array;

$array_r = increase_array_element($array_ref);

sub increase_array_element {
//recover the 2D array
my @array_tmp = @{$array_ref};
print $array_tmp[2][2];
return \@array_tmp;
}
//-------------------------

But it seems the compile did not think @array_tmp is a 2D array?

Thanks!
Davy
 
S

Sisyphus

Davy said:
Hi all,

I want to pass 2D array to sub function and return 2D array.

//--------------------------
For example,
use strict;
use warnings;
my @array=([1,2,3],[4,5,6],[7,8,9]);
my $array_ref = \@array;

$array_r = increase_array_element($array_ref);

sub increase_array_element {
//recover the 2D array
my @array_tmp = @{$array_ref};
print $array_tmp[2][2];
return \@array_tmp;
}
//-------------------------

But it seems the compile did not think @array_tmp is a 2D array?

Best to copy'n'paste code. The code you have posted won't compile.

Just as inside the subroutine where you dereferenced the array reference
($array_ref) to an array (@array_temp), you could do the same with $array_r
(which is also an array reference - since that is what the subroutine
returns).

Something like:

use strict;
use warnings;
my @array=([1,2,3],[4,5,6],[7,8,9]);
my $array_ref = \@array;

my $array_r = increase_array_element($array_ref);
my @array_r_r = @{$array_r};
print $array_r_r[1][1], "\n";

sub increase_array_element {
my @array_tmp = @{$array_ref};
print $array_tmp[2][2], "\n";
return \@array_tmp;
}

Cheers,
Rob
 
A

anno4000

Davy said:
Hi all,

I want to pass 2D array to sub function and return 2D array.

//--------------------------

That's not a valid Perl comment. It's a fatal error.
For example,
use strict;
use warnings;
my @array=([1,2,3],[4,5,6],[7,8,9]);
my $array_ref = \@array;

$array_r = increase_array_element($array_ref);

$array_r is undeclared. That's a fatal error under "strict".

Calling "increase_array_ref" with an argument is useless because
the sub doesn't look at its arguments.
sub increase_array_element {
//recover the 2D array
my @array_tmp = @{$array_ref};
print $array_tmp[2][2];
return \@array_tmp;
}
//-------------------------

See above.
But it seems the compile did not think @array_tmp is a 2D array?

How do you know that?

Your code doesn't compile at all, you didn't even bother to run it
before posting.

Make your program runnable. If it still doesn't do what you expect,
post again, explaining what you expected and what happens instead.

Anno
 
P

Paul Lalli

Sisyphus said:
Just as inside the subroutine where you dereferenced the array reference
($array_ref) to an array (@array_temp), you could do the same with $array_r
(which is also an array reference - since that is what the subroutine
returns).

Something like:

use strict;
use warnings;
my @array=([1,2,3],[4,5,6],[7,8,9]);
my $array_ref = \@array;

my $array_r = increase_array_element($array_ref);
my @array_r_r = @{$array_r};
print $array_r_r[1][1], "\n";

sub increase_array_element {
my @array_tmp = @{$array_ref};
print $array_tmp[2][2], "\n";
return \@array_tmp;
}


This code contains the same error as the OP's. You are passing this
subroutine an argument, but never obtaining that argument from within
the subroutine. It will "work" simply because the argument you passed
was declared within the scope of both the function definition and the
function call, but that's not what you want to do.

sub increase_array_element {
my @array_temp = @{$_[0]};
$array_tmp[2][2]++;
print $array_tmp[2][2], "\n";
return \@array_tmp;
}

Please note that because of the way multi-dimensional structures work
in Perl, both the original and modified arrays contain references to
the *same* arrays, and so you have actually modified both $array_r and
$array_ref. . .

Paul Lalli
 
S

Sisyphus

..
..
This code contains the same error as the OP's.

The code I posted does not contain any errors.

I was aware that the OP's subroutine took no arguments. If I had also
noticed that the OP was calling the subroutine *with* an argument then I
would have amended that when I did the copy'n'paste of his code. I did not
notice the OP had done this until Anno pointed it out.

It's good that you took the time to explain how to pass the argument to the
subroutine. I ignored that aspect because (I thought) the question asked was
concerned with the sub's *return* value - but given the subject line, your
explanation is certainly warranted.

Cheers,
Rob
 
P

Paul Lalli

Sisyphus said:
.
.

The code I posted does not contain any errors.

It does not contain any errors in that it will, indeed, work exactly as
posted. However, the general methodology given by your example will
not. Passing an argument into a subroutine and later referring to that
argument in the subroutine by the name it had as an argument to the
function call is an error. Because it "works" under a specific
circumstance (the call and the definition being in the same scope) does
not make it not an error.

Paul Lalli
 
D

Davy

Hi Lalli,

I have used your code and passed, thanks!

Davy

Paul said:
Sisyphus said:
Just as inside the subroutine where you dereferenced the array reference
($array_ref) to an array (@array_temp), you could do the same with $array_r
(which is also an array reference - since that is what the subroutine
returns).

Something like:

use strict;
use warnings;
my @array=([1,2,3],[4,5,6],[7,8,9]);
my $array_ref = \@array;

my $array_r = increase_array_element($array_ref);
my @array_r_r = @{$array_r};
print $array_r_r[1][1], "\n";

sub increase_array_element {
my @array_tmp = @{$array_ref};
print $array_tmp[2][2], "\n";
return \@array_tmp;
}


This code contains the same error as the OP's. You are passing this
subroutine an argument, but never obtaining that argument from within
the subroutine. It will "work" simply because the argument you passed
was declared within the scope of both the function definition and the
function call, but that's not what you want to do.

sub increase_array_element {
my @array_temp = @{$_[0]};
$array_tmp[2][2]++;
print $array_tmp[2][2], "\n";
return \@array_tmp;
}

Please note that because of the way multi-dimensional structures work
in Perl, both the original and modified arrays contain references to
the *same* arrays, and so you have actually modified both $array_r and
$array_ref. . .

Paul Lalli
 
D

Davy

No, I use Perl in my work. And I found reference in Perl is not so
clear as in C.

Anyhow, thanks.
Davy
 
U

Uri Guttman

D> No, I use Perl in my work. And I found reference in Perl is not so
D> clear as in C.

well, considering they are dramatically different, why should they be as
clear? c uses raw address pointers which can be manipulated, cast and
broken in too many ways to count. perl uses intelligent references which
can only be created by perl, can't be directly manipulated by user code
(no segfaults from perl refs) and can only be dereferenced to the
original thing that was referenced. does that sound like they are so
similar that knowing c pointers would make it clear how perl's refs
work? they have almost nothing in common.

and if you think c's pointers are clear and perl's refs are not, you
haven't done much deep data work and coding in either lang. i have done
plenty in both and i much prefer perl's refs. tracking segfaults is not
how i want to spend the rest of my life.

uri
 
D

Davy

Hi,

I understand. c's pointers are too flexible to generate bugs and Perl's
reference is more strict. Thanks!

Davy
 

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,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top