Re: passing part of an array to a function

2001-05-20 Thread David H. Adler

On Thu, May 17, 2001 at 11:33:55AM +1000, King, Jason wrote:
> Peter Scott writes ..
> 
> >At 10:44 AM 5/17/01 +1000, King, Jason wrote:
> >>so here's the thing .. Perl doesn't have pointers .. only references
> >>.. so you can't have a 1500 element array and grab a reference to the
> >>700th element
> >
> >Oh yes you can:
> >
> >my @foo = qw(three blind mice);
> >my $elemref = \$foo[2];
> 
> yes .. sorry - I phrased that badly .. I meant that you couldn't grab a
> reference to an array starting at the 700th element

I've lost the thread of what is *actually* being attempted here, but...

perl -e '@x = (1..100);$q = [@x[50..$#x]];print "@$q\n"'

which gives you a reference to the values at least.

Of course, that's just evil.  If that's what you're trying to do, there
must be a better way to do it.  In fact, you should probably forget I
even brought this up.

MOVE ALONG, NOTHING TO SEE HERE!  :-)

dha

-- 
David H. Adler - <[EMAIL PROTECTED]> - http://www.panix.com/~dha/
"You can't give a 4 to truth." - Saul Williams



Re: passing part of an array to a function

2001-05-17 Thread Gary Stainburn

Thanks for that explanation Jason, I'm always happier when I know *why* 
something doesn't work.

What I've ended up doing, and was also suggested in another branch of 
this thread was to pass a reference to the whole array, and a start and 
end index number.  This appears to provide the fastest running code.

Gary

On Thursday 17 May 2001  2:04 am, King, Jason wrote:
> Gary wrote ..
>
>  &file_control(\@lines[10..36]); # pass pointer to array elements
>
> I just wanted to add something for those that are interested in what
> the above actually does .. let's use an example
>
>   @foo = qw/a b c d e f g h i j/;
>
> then we do this
>
>   $bar = \@foo[3..6];
>
> what it does is creates an array slice (which is just a list) and
> then evaluates that list in scalar context (the 'taking the
> reference' is the lowest precedence) .. so the above is the same as
>
>   $bar = \qw/d e f g/;
>
> a list in scalar context evaluates to the last element of that list
> .. so the above becomes
>
>   $bar = \8;
>
> in other words .. $bar will end up with a reference to the last
> element of the slice .. so the original code is the same as
>
>   $bar = \$foo[6];
>
>
> it should be noted .. that even if there was some magical way of
> getting the reference to the array slice .. because Perl only has
> references and not pointers .. the array slice would still be copied
> (behind the scenes) to a new memory location
>
> with that caveat in place .. just for the curious onlookers .. this
> does what Gary thought he wanted
>
>   $bar = [ @foo[3..6] ];  # THIS MAKES A COPY OF THE ELEMENTS !!!
>
> but I repeat that the above makes a new copy of the elements on the
> array slice and THEN grabs a reference to that new memory .. the only
> array reference that can be grabbed without making a copy is a
> reference to the start of the @foo array

-- 
Gary Stainburn
 
This email does not contain private or confidential material as it
may be snooped on by interested government parties for unknown
and undisclosed purposes - Regulation of Investigatory Powers Act, 2000 




RE: passing part of an array to a function

2001-05-16 Thread King, Jason

Peter Scott writes ..

>At 10:44 AM 5/17/01 +1000, King, Jason wrote:
>>so here's the thing .. Perl doesn't have pointers .. only references
>>.. so you can't have a 1500 element array and grab a reference to the
>>700th element
>
>Oh yes you can:
>
>my @foo = qw(three blind mice);
>my $elemref = \$foo[2];

yes .. sorry - I phrased that badly .. I meant that you couldn't grab a
reference to an array starting at the 700th element

-- 
  jason king

  It is illegal to "annoy a bird" in any city park of Honolulu, Hawaii.
  - http://dumblaws.com/



RE: passing part of an array to a function

2001-05-16 Thread Peter Scott

At 10:44 AM 5/17/01 +1000, King, Jason wrote:
>so here's the thing .. Perl doesn't have pointers .. only references .. so
>you can't have a 1500 element array and grab a reference to the 700th
>element

Oh yes you can:

my @foo = qw(three blind mice);
my $elemref = \$foo[2];

>  .. because references don't work that way .. pointers work that way
>- but there aint no pointers in Perl

But as you say, you can't make a reference to a slice; you end up with a 
list of references to each element of the slice.  Pity.

Confirming that passing slices to subroutines results in copying:

$ perl -le 'system "ps -lp $$"; @x = 1..1_000_000; system "ps -lp 
$$";foo(@x[1..500_000]); system "ps -lp $$"; sub foo{}'
   F S   UID   PID  PPID  C PRI  NI ADDRSZ WCHAN  TTY  TIME CMD
000 S   500 30162 30128 96  68   0- 16513 wait4  pts/000:00:04 perl
   F S   UID   PID  PPID  C PRI  NI ADDRSZ WCHAN  TTY  TIME CMD
000 S   500 30162 30128 54  70   0- 19482 wait4  pts/000:00:08 perl
   F S   UID   PID  PPID  C PRI  NI ADDRSZ WCHAN  TTY  TIME CMD
000 S   500 30162 30128 51  69   0- 19971 wait4  pts/000:00:08 perl

So your solution of passing a ref to the whole array looks optimal.
--
Peter Scott
Pacific Systems Design Technologies
http://www.perldebugged.com




RE: passing part of an array to a function

2001-05-16 Thread King, Jason

Gary wrote ..

 &file_control(\@lines[10..36]); # pass pointer to array elements


I just wanted to add something for those that are interested in what the
above actually does .. let's use an example

  @foo = qw/a b c d e f g h i j/;

then we do this

  $bar = \@foo[3..6];

what it does is creates an array slice (which is just a list) and then
evaluates that list in scalar context (the 'taking the reference' is the
lowest precedence) .. so the above is the same as

  $bar = \qw/d e f g/;

a list in scalar context evaluates to the last element of that list .. so
the above becomes

  $bar = \8;

in other words .. $bar will end up with a reference to the last element of
the slice .. so the original code is the same as

  $bar = \$foo[6];


it should be noted .. that even if there was some magical way of getting the
reference to the array slice .. because Perl only has references and not
pointers .. the array slice would still be copied (behind the scenes) to a
new memory location

with that caveat in place .. just for the curious onlookers .. this does
what Gary thought he wanted

  $bar = [ @foo[3..6] ];  # THIS MAKES A COPY OF THE ELEMENTS !!!

but I repeat that the above makes a new copy of the elements on the array
slice and THEN grabs a reference to that new memory .. the only array
reference that can be grabbed without making a copy is a reference to the
start of the @foo array

-- 
  jason king

  It is illegal to "annoy a bird" in any city park of Honolulu, Hawaii.
  - http://dumblaws.com/



RE: passing part of an array to a function

2001-05-16 Thread King, Jason

Gary writes ..

>The whole point of using references was so that I didn't want to keep  
>copying array slices. This script will be handling nearly 1500 program 
>source files totalling almost 750k lines of code.  
>
>Any further help would be appreciated.


so here's the thing .. Perl doesn't have pointers .. only references .. so
you can't have a 1500 element array and grab a reference to the 700th
element .. because references don't work that way .. pointers work that way
- but there aint no pointers in Perl

so .. you have two choices


1. copy the elements that you want into a new memory location and send a
reference to that memory location into your subroutine (clearly non-ideal)


2. send the reference to the entire array into your subroutine and just work
with it .. you would also probably want to pass in the start index and end
index (or length if that's more helpful) .. eg.


  sub file_control
  {
my( $line, $start, $end) = @_;

for my $index ( $start..$end)   # process each line in array section
{
  # assign line to a localised $_ for convenience
  local $_ = $line->[$index];

  next if (/^  [\/\*]/);

  # ... etc.
}

  }

-- 
  jason king

  It is illegal to "annoy a bird" in any city park of Honolulu, Hawaii.
  - http://dumblaws.com/



Re: passing part of an array to a function

2001-05-16 Thread Gary Stainburn

The whole point of using references was so that I didn't want to keep 
copying array slices.  This script will be handling nearly 1500 program 
source files totalling almost 750k lines of code.  

Any further help would be appreciated.

Gary

On Tuesday 15 May 2001  5:32 pm, Jos Boumans wrote:
> Ok, let's hope i can shed some light on this situation.
>
> What's going wrong is that you are using a reference to an array
> slice... not sure why that's a big problem but it is apparently.
> in your case, there are 2 solutions:
>
> 1) do something like the following if you insist on using references
>
> @foo = (1,2,3,4,5,6,7,8,9);
> @baz = @foo[1..5];
> bar(\@baz);
>
> sub bar {
> my $aref = shift;
> for (@$aref) {print}
> }
>
> #which will nicely print '23456'
>
> 2) Seeing your passing an array slice to the sub, there is no real
> need for references, so you could do something like this:
>   @foo = (1,2,3,4,5,6,7,8,9);
>bar(@foo[1..5]);
>
> sub bar {
>  my @a = @_;
>  for (@a) {print}
> }
>
>  #which will nicely print '23456'
>
> I hope this will solve your problem for now...
>
> Regards,
>
> Jos Boumans
>
> Paul wrote:
> > --- Gary Stainburn <[EMAIL PROTECTED]> wrote:
> > > Hi all,
> >
> > Hi, Gary. =o)
> >
> > > I have an array that holds the source code to a cobol program.  I
> > > then have a number of integers that hold the subscript for
> > > section
> >
> > and
> >
> > > division changes.
> > > I then have subs that parse sections of that array. e.g. a sub
> > > called file_control will parse the file-control section and
> > > extract information from the file select statements.
> >
> > Actually, that sounds like a pretty cool arrangement.
> >
> > > At the moment my code works because I store the array as a global
> > > variable and pass to the sub the start and end array elements.
> >
> > Ah. A reasonable way to deal with the circumstance, but globals are
> > commonly considered "bad", lol
> >
> > > I want to now make my code a bit more flexible and simply pass a
> > > reference to the section I require.  The code I've tried may give
> > > a better idea of what i mean.  when I run my code I get the
> > > following error on the 'foreach (@$lines)' line
> > >
> > > Not an ARRAY reference at ./s line 109.
> >
> > Hmmlooking below, the cause is not immediately apparent to me.
> > In fact, what you've done was the first solution that popped into
> > my mind. (Somebody please explain the problem with that for me,
> > too?)
> >
> > > I could simply pass the array sections to the subroutines but
> > > that would be very inefficient - the procedure divisions of some
> > > the programs are 5k lines - hence the attempt to reference.
> >
> > I think this is a good candidate for an object.
> > Try this:
> >
> >   my $obj = {};
> >   $obj->{CODE} = [ @lines ];
> >
> > now you can undef @lines to recoup that memory (though Perl
> > probably won't give it back.)
> >
> > Then you can do neat things like putting the section indexes on the
> > object also:
> >
> >   $obj->{FILECTL} = $fc_ndx;
> >
> > Then all you have to do is pass the object to each function.
> >   file_control($obj);
> >
> > and they can grab the pieces they need off it.
> >
> >  sub func {
> >  my $obj = shift;
> >  for my $ndx ($obj->{SECTION1} .. ($obj->{SECTION2}-1)) {
> >  # code for section
> >  }
> >  }
> >
> > try looking at the perldocs for
> > perlref
> > perlreftut
> > perlobj
> > perlboot
> > perltoot
> > perltootc
> >
> > Paul
> >
> > (Original code left below for reader's convenience)
> >
> > > my @lines=( # simulate read cobol file
> > > 
> > > "   file-control.\r\n",
> > > "   select jobfile\r\n",
> > > "   assign external das1\r\n",
> > > "   organization is indexed\r\n",
> > > "   access dynamic\r\n",
> > > "   record key is job-jf-key\r\n",
> > > "   file status is w01-jobf-stat\r\n",
> > > "   lock mode is automatic with rollback.\r\n",
> > > ...
> > >
> > > &file_control(\@lines[10..36]); # pass pointer to array elements
> > > 10-36
> > >
> > > sub file_control() {
> > >   my ($lines)=@_;
> > >   foreach (@$lines) {   # process each line in array section
> > > next if (/^  [\/\*]/);
> > > 
> >
> > __
> > Do You Yahoo!?
> > Yahoo! Auctions - buy the things you want at great prices
> > http://auctions.yahoo.com/

-- 
Gary Stainburn
 
This email does not contain private or confidential material as it
may be snooped on by interested government parties for unknown
and undisclosed purposes - Regulation of Investigatory Powers Act, 2000 




Re: passing part of an array to a function

2001-05-15 Thread Jos Boumans

Ok, let's hope i can shed some light on this situation.

What's going wrong is that you are using a reference to an array slice...
not sure why that's a big problem but it is apparently.
in your case, there are 2 solutions:

1) do something like the following if you insist on using references

@foo = (1,2,3,4,5,6,7,8,9);
@baz = @foo[1..5];
bar(\@baz);

sub bar {
my $aref = shift;
for (@$aref) {print}
}

#which will nicely print '23456'

2) Seeing your passing an array slice to the sub, there is no real need for
references, so you could do something like this:
  @foo = (1,2,3,4,5,6,7,8,9);
   bar(@foo[1..5]);

sub bar {
 my @a = @_;
 for (@a) {print}
}

 #which will nicely print '23456'

I hope this will solve your problem for now...

Regards,

Jos Boumans

Paul wrote:

> --- Gary Stainburn <[EMAIL PROTECTED]> wrote:
> > Hi all,
>
> Hi, Gary. =o)
>
> > I have an array that holds the source code to a cobol program.  I
> > then have a number of integers that hold the subscript for section
> and
> > division changes.
> > I then have subs that parse sections of that array. e.g. a sub called
> > file_control will parse the file-control section and extract
> > information from the file select statements.
>
> Actually, that sounds like a pretty cool arrangement.
>
> > At the moment my code works because I store the array as a global
> > variable and pass to the sub the start and end array elements.
>
> Ah. A reasonable way to deal with the circumstance, but globals are
> commonly considered "bad", lol
>
> > I want to now make my code a bit more flexible and simply pass a
> > reference to the section I require.  The code I've tried may give a
> > better idea of what i mean.  when I run my code I get the following
> > error on the 'foreach (@$lines)' line
> >
> > Not an ARRAY reference at ./s line 109.
>
> Hmmlooking below, the cause is not immediately apparent to me.
> In fact, what you've done was the first solution that popped into my
> mind. (Somebody please explain the problem with that for me, too?)
>
> > I could simply pass the array sections to the subroutines but that
> > would be very inefficient - the procedure divisions of some the
> > programs are 5k lines - hence the attempt to reference.
>
> I think this is a good candidate for an object.
> Try this:
>
>   my $obj = {};
>   $obj->{CODE} = [ @lines ];
>
> now you can undef @lines to recoup that memory (though Perl probably
> won't give it back.)
>
> Then you can do neat things like putting the section indexes on the
> object also:
>
>   $obj->{FILECTL} = $fc_ndx;
>
> Then all you have to do is pass the object to each function.
>   file_control($obj);
>
> and they can grab the pieces they need off it.
>
>  sub func {
>  my $obj = shift;
>  for my $ndx ($obj->{SECTION1} .. ($obj->{SECTION2}-1)) {
>  # code for section
>  }
>  }
>
> try looking at the perldocs for
> perlref
> perlreftut
> perlobj
> perlboot
> perltoot
> perltootc
>
> Paul
>
> (Original code left below for reader's convenience)
>
> > my @lines=( # simulate read cobol file
> > 
> > "   file-control.\r\n",
> > "   select jobfile\r\n",
> > "   assign external das1\r\n",
> > "   organization is indexed\r\n",
> > "   access dynamic\r\n",
> > "   record key is job-jf-key\r\n",
> > "   file status is w01-jobf-stat\r\n",
> > "   lock mode is automatic with rollback.\r\n",
> > ...
> >
> > &file_control(\@lines[10..36]); # pass pointer to array elements
> > 10-36
> >
> > sub file_control() {
> >   my ($lines)=@_;
> >   foreach (@$lines) {   # process each line in array section
> > next if (/^  [\/\*]/);
> > 
>
> __
> Do You Yahoo!?
> Yahoo! Auctions - buy the things you want at great prices
> http://auctions.yahoo.com/




Re: passing part of an array to a function

2001-05-15 Thread Paul

--- Gary Stainburn <[EMAIL PROTECTED]> wrote:
> Hi all,

Hi, Gary. =o)

> I have an array that holds the source code to a cobol program.  I
> then have a number of integers that hold the subscript for section
and 
> division changes.
> I then have subs that parse sections of that array. e.g. a sub called
> file_control will parse the file-control section and extract 
> information from the file select statements.

Actually, that sounds like a pretty cool arrangement.

> At the moment my code works because I store the array as a global 
> variable and pass to the sub the start and end array elements.

Ah. A reasonable way to deal with the circumstance, but globals are
commonly considered "bad", lol
 
> I want to now make my code a bit more flexible and simply pass a 
> reference to the section I require.  The code I've tried may give a 
> better idea of what i mean.  when I run my code I get the following 
> error on the 'foreach (@$lines)' line
> 
> Not an ARRAY reference at ./s line 109.

Hmmlooking below, the cause is not immediately apparent to me.
In fact, what you've done was the first solution that popped into my
mind. (Somebody please explain the problem with that for me, too?)
 
> I could simply pass the array sections to the subroutines but that 
> would be very inefficient - the procedure divisions of some the 
> programs are 5k lines - hence the attempt to reference.

I think this is a good candidate for an object.
Try this:

  my $obj = {};
  $obj->{CODE} = [ @lines ]; 

now you can undef @lines to recoup that memory (though Perl probably
won't give it back.)

Then you can do neat things like putting the section indexes on the
object also:

  $obj->{FILECTL} = $fc_ndx;

Then all you have to do is pass the object to each function.
  file_control($obj);

and they can grab the pieces they need off it.

 sub func {
 my $obj = shift;
 for my $ndx ($obj->{SECTION1} .. ($obj->{SECTION2}-1)) {
 # code for section
 }
 }
 
try looking at the perldocs for
perlref
perlreftut
perlobj
perlboot
perltoot
perltootc

Paul

(Original code left below for reader's convenience)

> my @lines=( # simulate read cobol file
> 
> "   file-control.\r\n",
> "   select jobfile\r\n",
> "   assign external das1\r\n",
> "   organization is indexed\r\n",
> "   access dynamic\r\n",
> "   record key is job-jf-key\r\n",
> "   file status is w01-jobf-stat\r\n",
> "   lock mode is automatic with rollback.\r\n",
> ...
> 
> &file_control(\@lines[10..36]); # pass pointer to array elements
> 10-36
> 
> sub file_control() {
>   my ($lines)=@_;
>   foreach (@$lines) {   # process each line in array section
> next if (/^  [\/\*]/);
> 


__
Do You Yahoo!?
Yahoo! Auctions - buy the things you want at great prices
http://auctions.yahoo.com/