subroutine array question
Anonymous Monk
created: 2006-08-02 09:18:31
Hi Monks,
what am I doing wrong here:
my @area = &circ_area(5,6,7);
foreach (@area)
{
          print $_ . "\n";
}

sub circ_area
{
    foreach (@_)
    {
         $_= 3.14 * ($_**2);
    }
    return (@_)
}
Thanks,
Jonathan
Re: subroutine array question
created: 2006-08-02 09:23:14

The error message tells you

Modification of a read-only value attempted

So re-write it:

#!/bin/perl
use strict;
use warnings;

my @vals = ( 5, 6, 7 );

my @area = &circ_area( @vals );
foreach (@area)
{
          print $_ . "\n";
}

sub circ_area
{
    foreach (@_)
    {
         $_= 3.14 * ($_**2);
    }
    return (@_)
}

But since you're modifying the @_ var ... you really don't need to return it ... you're just needlessly copying the data.

#!/bin/perl
use strict;
use warnings;

my @vals = ( 5, 6, 7 );

&circ_area( @vals );
foreach (@vals)
{
          print $_ . "\n";
}

sub circ_area
{
    foreach (@_)
    {
         $_= 3.14 * ($_**2);
    }
}

-derby
Re: subroutine array question
created: 2006-08-02 09:26:14
what am I doing wrong here

You are trying to modify 5, 6, and 7. It's a good thing Perl does not let you, or math would be a tricky thing to do.

You might want to make some copies, somewhere or other. Since your function is returning values, you probably don't want it to also change the input values, and so I would choose to make the copies there:

my @area = &circ_area(5,6,7);
foreach (@area) {
    print $_ . "\n";
}

sub circ_area {
    my @x = @_; # the copy is writable!
    foreach (@x) {
         $_= 3.14 * ($_**2); # so this works!
    }
    return (@x)
}

print "Just another Perl ${\(trickster and hacker)},"
The Sidhekin proves Sidhe did it!

Re: subroutine array question
created: 2006-08-02 09:27:52

It'd be helpful if you showed any error messages or explained what you got vs what you expected to get.

You seem to be using the parameters to circ_area as rvalues when you modify each parameter in turn. This will modify the original values as passed in, except that those values are constants and not modifyable. Then you return them - so that's just confusing. Why modify in place, and then return new copies?

Also, you don't need the &. So get rid of it.

Option 1:

my @area = (5,6,7);
circ_area(@area);
# rest as-is
Of course, this makes your code a liar - the area of those circles aren't 5, 6, and 7. The values are misleading until after the call to circ_area.

Option 2:

# rest as-is
sub circ_area
{
  map { 3.14 * ($_ ** 2) } @_;
}
Here we are creating a new array by mapping from the input values to some new output values. Since we don't assign back to $_, we aren't overwriting the constant inputs. This would be the way I suggest going.

Re: subroutine array question
created: 2006-08-02 09:27:55

You're trying to modify read-only values (as Perl has no doubt told you).

Inside your subroutine, @_ contains three values (5, 6 and 7). But they aren't just values, they are the constants 5, 6 and seven. And in the foreach loop, $_ is aliases to each of those constants in turn. So when you try to assign a new value to $_, you are trying to overwrite the value of a constant. Which Perl, very sensibly, prevents you from doing.

What you really want is something like this:

sub circ_area {
  my @radii = @_; # copies values into a variable

  foreach (@radii) {
    $_= 3.14 * ($_**2);
  }

  return @radii;
}

Or, more Perlishly:

sub circ_area {
  return map { 3.14 * ($_**2) } @_;
}
--
<http://dave.org.uk>

"The first rule of Perl club is you do not talk about Perl club."
-- Chip Salzenberg

perlmonks.org content © perlmonks.org and Anonymous Monk, davorg, derby, Sidhekin, Tanktalus

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03