question on reference to array slice

R

Rick

Hi, guys

In C we can store a set of pointers which point to different arrays
into an array of pointer. This way we could fast access different
array by looking it up in this pointer array. Is there anyway to do
this in Perl. I've been trying different things and no luck so far.

LIke:
@nums = (1 .. 20);

I want to store the reference to @nums[1..10] into $data[0], and the
reference to @nums[11:20] into $data[1], so that I could visit, for
example, the second set of @nums by something like $data[1][5] to get
15.

Is this possible for Perl anyway?

Any input is really appreciated!!

-PD
 
G

Gunnar Hjalmarsson

Rick said:
In C we can store a set of pointers which point to different arrays
into an array of pointer. This way we could fast access different
array by looking it up in this pointer array. Is there anyway to do
this in Perl. I've been trying different things and no luck so far.

LIke:
@nums = (1 .. 20);

I want to store the reference to @nums[1..10] into $data[0], and the
reference to @nums[11:20] into $data[1], so that I could visit, for
example, the second set of @nums by something like $data[1][5] to get
15.

Is this possible for Perl anyway?

my @nums = 1 .. 20;
my @data;

for ( my $i=0; $i<=$#nums; $i=$i+10 ) { # assigns references to
push @data, [ @nums[$i..$i+9] ]; # copies of respective
} # array slice to @data

print $data[1][5]; # prints 16
 
M

Mirco Wahab

Rick said:
In C we can store a set of pointers which point to different arrays
into an array of pointer. This way we could fast access different
array by looking it up in this pointer array. Is there anyway to do
this in Perl. I've been trying different things and no luck so far.

LIke:
@nums = (1 .. 20);

I want to store the reference to @nums[1..10] into $data[0], and the
reference to @nums[11:20] into $data[1], so that I could visit, for
example, the second set of @nums by something like $data[1][5] to get
15.

Is this possible for Perl anyway?

No

You can't do that in Perl because "arrays"
aren't continous memory blocks (C/C++),
but rather _already_ pointer arrays
(pointers to elements as array values)
with a somehow complicated management
built around.

Furthermore, you can't "jump" in the
middle of something arraylike and
expect to find a mechanism there
which treats the rest as a Perl
array.

The only way to come close is the
_copying_ of an array element range
(slice) into a new (anonymous) array,
as Gunnar has already shown.

Regards

M.
 
J

John W. Krahn

Rick said:
In C we can store a set of pointers which point to different arrays
into an array of pointer. This way we could fast access different
array by looking it up in this pointer array. Is there anyway to do
this in Perl. I've been trying different things and no luck so far.

LIke:
@nums = (1 .. 20);

I want to store the reference to @nums[1..10] into $data[0], and the
reference to @nums[11:20] into $data[1], so that I could visit, for
example, the second set of @nums by something like $data[1][5] to get
15.

$ perl -le'
@nums = 1 .. 20;
print "@nums";
$data[ 0 ] = [ \@nums[ 0 .. 9 ] ];
$data[ 1 ] = [ \@nums[ 10 .. 19 ] ];
print ${ $data[ 1 ][ 5 ] };
${ $data[ 1 ][ 5 ] } = 0;
print "@nums";
'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 17 18 19 20




John
 
M

Mirco Wahab

John said:
$data[ 0 ] = [ \@nums[ 0 .. 9 ] ];
$data[ 1 ] = [ \@nums[ 10 .. 19 ] ];

This usage of slice reference is something I
didn't consider. So Bellovins word was right
again: "any software problem can be solved by
adding another layer of indirection."

"anonymous slice reference" - thanks
for pointing me on this.

Regards

M.
 
G

Gunnar Hjalmarsson

Mirco said:
John said:
$data[ 0 ] = [ \@nums[ 0 .. 9 ] ];
$data[ 1 ] = [ \@nums[ 10 .. 19 ] ];

This usage of slice reference is something I
didn't consider. So Bellovins word was right
again: "any software problem can be solved by
adding another layer of indirection."

"anonymous slice reference"

AFAIU, they don't really refer to the slice, but rather to arrays which
in turn refer to the individual elements.

C:\>perl -MData::Dumper -e "@nums=1..20;print Dumper [ \@nums[0..9] ]"
$VAR1 = [
\1,
\2,
\3,
\4,
\5,
\6,
\7,
\8,
\9,
\10
];

C:\>
 
A

attn.steven.kuo

Rick said:
In C we can store a set of pointers which point to different arrays
into an array of pointer. This way we could fast access different
array by looking it up in this pointer array. Is there anyway to do
this in Perl. I've been trying different things and no luck so far.
LIke:
@nums = (1 .. 20);
I want to store the reference to @nums[1..10] into $data[0], and the
reference to @nums[11:20] into $data[1], so that I could visit, for
example, the second set of @nums by something like $data[1][5] to get
15.
Is this possible for Perl anyway?

No

You can't do that in Perl because "arrays"
aren't continous memory blocks (C/C++),
but rather _already_ pointer arrays
(pointers to elements as array values)
with a somehow complicated management
built around.

Furthermore, you can't "jump" in the
middle of something arraylike and
expect to find a mechanism there
which treats the rest as a Perl
array.

The only way to come close is the
_copying_ of an array element range
(slice) into a new (anonymous) array,
as Gunnar has already shown.



You can try the tie function (perldoc perltie). E.g.,

package Tie::Slice;
use Tie::Array;
@ISA = qw/Tie::Array/;

sub TIEARRAY {
my $class = shift;
my $aref = shift;
my $offset = shift;
my $length = shift || (@$aref - $offset);
return bless {
AREF => $aref,
OFFSET => $offset,
LENGTH => $length,
}, $class;
}

sub FETCH {
my ($self, $index) = @_;
if ($index >= 0) {
return $self->{AREF}->[$self->{OFFSET}+$index];
} else {
my $subtracted = $self->{OFFSET} + $self->{LENGTH};
return $self->{AREF}->[$index - $subtracted];
}
}

sub FETCHSIZE {
my ($self) = @_;
return $self->{LENGTH};
}

# no methods added for writing to array (e.g., STORE, STORESIZE,
etc.).

package main;
use strict;
use warnings;

my @nums = ( 1 .. 20 );
my (@first_half, @second_half);
tie @first_half, 'Tie::Slice', \@nums, 0, 10;
tie @second_half, 'Tie::Slice', \@nums, 10;
my @data = (\@first_half, \@second_half);

print $data[1][5];


__END__

Note that changes made to @nums will be automatically
reflected in @data (but not visa-versa since I've
only implemented the methods needed for "reading" in
Tie::Slice).
 
P

Paul Lalli

John said:
$data[ 0 ] = [ \@nums[ 0 .. 9 ] ];
$data[ 1 ] = [ \@nums[ 10 .. 19 ] ];

This usage of slice reference is something I
didn't consider. So Bellovins word was right
again: "any software problem can be solved by
adding another layer of indirection."

"anonymous slice reference" - thanks
for pointing me on this.

I wouldn't call it a slice reference. An array slice is a list. The
\ operator applied to a list returns a list of references of the items
in that list. That is:

my @refs = \($a, $b, $c);
is the same as
my @refs = (\$a, \$b, \$c);

So in John's example, you're assigning $data[0] to be a reference to
an array which contains references to each of the first ten elements
of @nums. There is nothing intrinsic about $data[0][2] that
identifies it as a reference to the element immediately prior to
$nums[3]. It's just a list of references to values that happened to
all come from the same array.

Paul Lalli
 
T

Ted Zlatanov

R> Hi, guys
R> In C we can store a set of pointers which point to different arrays
R> into an array of pointer. This way we could fast access different
R> array by looking it up in this pointer array. Is there anyway to do
R> this in Perl. I've been trying different things and no luck so far.

R> LIke:
R> @nums = (1 .. 20);

R> I want to store the reference to @nums[1..10] into $data[0], and the
R> reference to @nums[11:20] into $data[1], so that I could visit, for
R> example, the second set of @nums by something like $data[1][5] to get
R> 15.

R> Is this possible for Perl anyway?

It depends on your purpose. If you aim for speed, just use C (Inline::C
for example). Otherwise, to make your own and everyone else's life
easier, use a function to translate the offsets or a constant. Even
better, explain what you're trying to do; it may be that hashes or
multidimensional arrays or array slices are the right answer for you.

Note you don't have to call the offset function every time, only at the
beginning to find out the offset. So it's not a big speed penalty.

Of course, you can always write your own Tie module, but those are IMHO
the last resort.

Ted
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top