Home > Archive > PERL Beginners > April 2007 > improving my code: array of references
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
improving my code: array of references
|
|
| Pierre Mariani 2007-04-26, 6:58 pm |
| Hello everyone,
I have a 'modify_variable' function that, well, modifies a variable.
I want to run it on several variables.
I have the following code that:
- builds an array of references on the variables,
- calls the function on the content of the reference,
- set the content of the reference to the result of the function.
# $var1, $var2 and $var3 are set previously
for ( \$var1,
\$var2,
\$var3,
)
{
${$_} = modify_variable ( ${$_} );
}
Questions:
- How do I improve my array definition?
- How to I call the modify_variable function in a more elegant way?
Thanks in advance.
| |
| Rodrick Brown 2007-04-26, 6:58 pm |
| Perfect canidate for Map.
On 4/26/07, Pierre Mariani <frenchyp@gmail.com> wrote:
> Hello everyone,
>
> I have a 'modify_variable' function that, well, modifies a variable.
>
> I want to run it on several variables.
>
> I have the following code that:
> - builds an array of references on the variables,
> - calls the function on the content of the reference,
> - set the content of the reference to the result of the function.
>
>
> # $var1, $var2 and $var3 are set previously
>
> for ( \$var1,
> \$var2,
> \$var3,
> )
>
> {
> ${$_} = modify_variable ( ${$_} );
> }
>
> Questions:
> - How do I improve my array definition?
> - How to I call the modify_variable function in a more elegant way?
>
> Thanks in advance.
>
>
> --
> To unsubscribe, e-mail: beginners-unsubscribe@perl.org
> For additional commands, e-mail: beginners-help@perl.org
> http://learn.perl.org/
>
>
>
--
Rodrick R. Brown
http://www.rodrickbrown.com
| |
| Pierre Mariani 2007-04-26, 6:58 pm |
| > # $var1, $var2 and $var3 are set previously[color=darkred]
>
[color=darkred]
Thanks for that.
So now I have:
my @tmp = ( $var1, $var2, $var3 );
@tmp = map modify_variable, @tmp;
which is better.
I don't think I can use references anymore using this method, but anyone know how to create an array of references?
Thanks
| |
| Paul Johnson 2007-04-26, 6:58 pm |
| On Thu, Apr 26, 2007 at 03:26:02PM -0700, Pierre Mariani wrote:
> anyone know how to create an array of references?
my @a = \($a, $b, $c);
--
Paul Johnson - paul@pjcj.net
http://www.pjcj.net
| |
| Matthew J. Avitable 2007-04-26, 9:58 pm |
| Hi Pierre,
> my @tmp = ( $var1, $var2, $var3 );
> @tmp = map modify_variable, @tmp;
>
> which is better
Conway (in Perl Best Practices) prefers the block form of map, since in
his opinion, it's more readable. So you could rewrite it as:
my @tmp = ( $var1, $var2, $var3 );
@tmp = map { modify_variable } @tmp
I'm guessing that the code within modify_variable uses $_ under the
hood? That may end up biting you later on, if you use modify_variable
in different places. If $_ is in use by other code or gets changed on
you unexpectedly, you may have some difficult debugging ahead of you.
The following may prove clearer when reading it 6 months from now:
map { modify_variable($_) } = \($var1, $var2, $var3);
I personally like the above syntax - others may not. A foreach gets you
an alias to each element, so what about the following? I've provided a
modify_var sub as an example.
$var1 = 1;
$var2 = 2;
$var3 = 3;
foreach my $v ($var1, $var2, $var3) {
modify_var(\$v);
}
sub modify_var {
my $scalar_ref = shift || die "blaaaaa";
${$scalar_ref} += 5;
}
$, = "\n"; ## print a newline between each argument to print
print ($var1, $var2, $var3);
-m
| |
| Rob Dixon 2007-04-27, 3:58 am |
| Pierre Mariani wrote:
> Hello everyone,
>
> I have a 'modify_variable' function that, well, modifies a variable.
>
> I want to run it on several variables.
>
> I have the following code that:
> - builds an array of references on the variables,
> - calls the function on the content of the reference,
> - set the content of the reference to the result of the function.
>
>
> # $var1, $var2 and $var3 are set previously
>
> for ( \$var1,
> \$var2,
> \$var3,
> )
>
> {
> ${$_} = modify_variable ( ${$_} );
> }
>
> Questions:
> - How do I improve my array definition?
> - How to I call the modify_variable function in a more elegant way?
I have a number of problems with this:
- It's unclear whether you have a fixed set of variables to process. Is
the list always the same?
- Why are you using references? Are you sure you need to?
- modify_variable() doesn't appear to modify anything, otherwise why are
you assigning its return value to the scalar passed as a parameter? It
seems to be just a function.
From what I can see, you need no more than:
$_ = function($_) foreach ($var1, $var2, $var3);
Will this do? Or is there more to the problem than you've explained?
Rob
| |
| Pierre Mariani 2007-04-27, 6:58 pm |
| Matthew and Rob, thank you for your replies.
> - It's unclear whether you have a fixed set of variables to process.
> Is
> the list always the same?
Yes, the list is always the same.
> - Why are you using references? Are you sure you need to?
>
> - modify_variable() doesn't appear to modify anything, otherwise why
> are
> you assigning its return value to the scalar passed as a parameter?
> It
> seems to be just a function.
Modify_variable modifies its input variable.
Please correct me if I am wrong.
My understanding is that:
1) if I do:
my @array = ($a, $b, $c);
for (@array) { $_ = modify_variable($_)}
I am going to modify $array[0], $array[1] and $array[2], and NOT $a, $b,
$c.
2) if I do:
for ($a, $b, $c) {$_ = modify_variable($_)}
I am going to modify $a, $b, $c, which is good, but if $a, $b, $c are
big I am going to be passing around lots of data.
So I think that using 2) with references on variables would be the ideal
solution.
>
> $_ = function($_) foreach ($var1, $var2, $var3);
>
> Will this do? Or is there more to the problem than you've explained?
Yes, that works in my case. I just thought that there might be a more
"elegant" way of doing it.
> Conway (in Perl Best Practices) prefers the block form of map, since in
> his opinion, it's more readable. So you could rewrite it as:
>
> my @tmp = ( $var1, $var2, $var3 );
> @tmp = map { modify_variable } @tmp
>
> I'm guessing that the code within modify_variable uses $_ under the
> hood? That may end up biting you later on, if you use modify_variable
> in different places. If $_ is in use by other code or gets changed on
> you unexpectedly, you may have some difficult debugging ahead of you.
> The following may prove clearer when reading it 6 months from now:
>
> map { modify_variable($_) } = \($var1, $var2, $var3);
I like this syntax too. The only difference in my case is that
modify_variable works with the content of the variable, not with a
reference (and I can't modify it).
So I will have to write it this way:
map { modify_variable(${$_}) } = \($var1, $var2, $var3);
Thank you for your advices.
| |
| John W. Krahn 2007-04-27, 6:58 pm |
| Pierre Mariani wrote:
> Matthew and Rob, thank you for your replies.
>
>
> Yes, the list is always the same.
>
>
> Modify_variable modifies its input variable.
>
> Please correct me if I am wrong.
> My understanding is that:
> 1) if I do:
> my @array = ($a, $b, $c);
> for (@array) { $_ = modify_variable($_)}
> I am going to modify $array[0], $array[1] and $array[2], and NOT $a, $b,
> $c.
Yes because the contents of $a, $b and $c are copied to @array so there is no
way that modifying the contents of @array will affect the contents of $a, $b
and $c.
> 2) if I do:
> for ($a, $b, $c) {$_ = modify_variable($_)}
> I am going to modify $a, $b, $c, which is good, but if $a, $b, $c are
> big I am going to be passing around lots of data.
Yes and in your example 1 above you are passing around lots of data twice. If
you don't want to pass around a lot of data then use references and change the
modify_variable() sub to work with references.
John
--
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order. -- Larry Wall
| |
| Chas Owens 2007-04-27, 6:58 pm |
| On 4/27/07, Pierre Mariani <frenchyp@gmail.com> wrote:
snip
>
> Modify_variable modifies its input variable.
I think the issue is what you mean by "modifies". In order to say
that the modify_variable function modifies its input then something
like the following must be true:
my $foo = 5
modify_variable($foo)
print "$foo\n"; #prints "6\n"
>
> Please correct me if I am wrong.
> My understanding is that:
> 1) if I do:
> my @array = ($a, $b, $c);
> for (@array) { $_ = modify_variable($_)}
> I am going to modify $array[0], $array[1] and $array[2], and NOT $a, $b,
> $c.
Yes, that is correct, but this is most likely an invalid use of an
array. Either you should be using a array from the beginning, or you
should be using a list. Assigning a bunch of scalar variables to an
array just to group them is useless.
$_ = modify_variable($_) for $a, $b, $c;
is a better construct. However, it would be even better to make
modify_variable take multiple arguments:
($a, $b, $c) = modify_variables($a, $b, $c);
>
> 2) if I do:
> for ($a, $b, $c) {$_ = modify_variable($_)}
> I am going to modify $a, $b, $c, which is good, but if $a, $b, $c are
> big I am going to be passing around lots of data.
Ah, here is the crux of the problem. You thing you are passing
copies. Perl aliases its arguments to functions. In C++ terms you
are passing by reference (if I got the terminology right). Passing
"this is a really long string" and "a" both take up the same amount of
time and memory. Only passing around arrays and hashes take up O(n)
space and time. That is why it is good form to pass them as
references.
snip[color=darkred]
snip
$_ = function($_) foreach ($var1, $var2, $var3);
is the same as
foreach ($var1, $var2, $var3) {
$_ = function($_)
}
If you only have one statement* in a loop for can write it in the
former method. It is considered by many to be clearer.
* well, you can chain statements using , but that is poor form outside
of Perl Golf, Obfuscation, and one-liners.
| |
| Pierre Mariani 2007-04-27, 6:58 pm |
| On Fri, 2007-04-27 at 12:03 -0400, Chas Owens wrote:
> On 4/27/07, Pierre Mariani <frenchyp@gmail.com> wrote:
> snip
>
> I think the issue is what you mean by "modifies". In order to say
> that the modify_variable function modifies its input then something
> like the following must be true:
>
> my $foo = 5
> modify_variable($foo)
> print "$foo\n"; #prints "6\n"
>
Yeah, that's exactly it.
>
>
> Yes, that is correct, but this is most likely an invalid use of an
> array. Either you should be using a array from the beginning, or you
> should be using a list. Assigning a bunch of scalar variables to an
> array just to group them is useless.
Agree on that, but given other details that I didn't communicate, it is
not quite possible (this is actually a pl/perlu function in postgresql,
the variables I am working on are passed to the function, and their type
is limited by the function definition, so unless I create a composite
type I can't pass them as an array directly).
> $_ = modify_variable($_) for $a, $b, $c;
>
> is a better construct. However, it would be even better to make
> modify_variable take multiple arguments:
>
> ($a, $b, $c) = modify_variables($a, $b, $c);
I agree on that (even better would be to make it work on references),
but unfortunately I can't modify it.
>
> Ah, here is the crux of the problem. You thing you are passing
> copies. Perl aliases its arguments to functions. In C++ terms you
> are passing by reference (if I got the terminology right). Passing
> "this is a really long string" and "a" both take up the same amount of
> time and memory. Only passing around arrays and hashes take up O(n)
> space and time. That is why it is good form to pass them as
> references.
>
> snip
> snip
>
> $_ = function($_) foreach ($var1, $var2, $var3);
>
> is the same as
>
> foreach ($var1, $var2, $var3) {
> $_ = function($_)
> }
>
> If you only have one statement* in a loop for can write it in the
> former method. It is considered by many to be clearer.
>
>
> * well, you can chain statements using , but that is poor form outside
> of Perl Golf, Obfuscation, and one-liners.
Thank you for the information. I was familiar with this kind of syntax
but never used it.
| |
| Chas Owens 2007-04-27, 6:58 pm |
| On 4/27/07, Pierre Mariani <frenchyp@gmail.com> wrote:
> On Fri, 2007-04-27 at 12:03 -0400, Chas Owens wrote:
>
> Yeah, that's exactly it.
Then why are you doing this
$_ = modify_variable($_)
in all of your examples?
snip
> Agree on that, but given other details that I didn't communicate, it is
> not quite possible (this is actually a pl/perlu function in postgresql,
> the variables I am working on are passed to the function, and their type
> is limited by the function definition, so unless I create a composite
> type I can't pass them as an array directly).
snip
Perhaps you should describe the full situation then. Without that
information we will not be able to help you very much; we will end up
just shooting in the dark at what we think the problem is.
| |
| Pierre Mariani 2007-04-27, 6:58 pm |
| On Fri, 2007-04-27 at 12:45 -0400, Chas Owens wrote:
> On 4/27/07, Pierre Mariani <frenchyp@gmail.com> wrote:
>
Sorry, I realize I replied to fast and was wrong. The way the function
works is:
my $foo = 5;
$foo = modify_variable($foo);
print "$foo\n"; #prints "6\n"
> Then why are you doing this
>
> $_ = modify_variable($_)
>
> in all of your examples?
> snip
> snip
>
> Perhaps you should describe the full situation then. Without that
> information we will not be able to help you very much; we will end up
> just shooting in the dark at what we think the problem is.
Thank you, but I got it to work the way I wanted, thanks to Matthew and
Rob's posts:
map { modify_variable(${$_}) } = \($var1, $var2, $var3);
I was continuing the discussion just for the sake of it...
| |
| Paul Johnson 2007-04-27, 6:58 pm |
| On Fri, Apr 27, 2007 at 09:54:37AM -0700, Pierre Mariani wrote:
> Thank you, but I got it to work the way I wanted, thanks to Matthew and
> Rob's posts:
>
> map { modify_variable(${$_}) } = \($var1, $var2, $var3);
I think you'll find that syntax is incorrect.
And map in void context is generally frowned upon.
modify_variable $$_ for \($var1, $var2, $var3);
Or assign it back to $$_ if that is necessary. If you're passing in a
reference is probably isn't. And given the name of the function, it
probably shouldn't be.
--
Paul Johnson - paul@pjcj.net
http://www.pjcj.net
| |
| Matthew J. Avitable 2007-04-27, 6:58 pm |
| Pierre,
To annotate to what Paul said - the above won't work. The block syntax
of map is "map BLOCK LIST". Plus, it looks like you are going to
dereference $_ before it gets passed into the function. I'm not
particularly sure what the statement above will do. :) The following
should work, if your version of modify_variable treats its first
argument as a scalar reference. See my earlier post for an example of
how modify_variable could work.
map { modify_variable($_) } \($var1, $var2, $var3);
[color=darkred]
> And map in void context is generally frowned upon.
>
There's lots of heated debate about this apparently. I'm certainly not
into starting a flame war, so I'll just point out an interesting
conversation which explores this topic, pretty well in depth.
http://www.perlmonks.org/index.pl?node_id=296742
-m
--
+ Matt J. Avitable: Senior Systems Analyst, Richweb, Inc.
+ Richweb.com: Providing Internet-Based Business Solutions since 1995
+ (804) 747.8592 x 109
| |
| Pierre Mariani 2007-04-27, 6:58 pm |
| On Fri, 2007-04-27 at 14:26 -0400, Matthew J. Avitable wrote:
> Pierre,
>
> To annotate to what Paul said - the above won't work. The block syntax
> of map is "map BLOCK LIST". Plus, it looks like you are going to
> dereference $_ before it gets passed into the function. I'm not
> particularly sure what the statement above will do. :) The following
> should work, if your version of modify_variable treats its first
> argument as a scalar reference. See my earlier post for an example of
> how modify_variable could work.
>
> map { modify_variable($_) } \($var1, $var2, $var3);
Good catch. My code would not have compiled with the '=' sign. I should
pay more attention. Thanks
>
>
> There's lots of heated debate about this apparently. I'm certainly not
> into starting a flame war, so I'll just point out an interesting
> conversation which explores this topic, pretty well in depth.
>
> http://www.perlmonks.org/index.pl?node_id=296742
>
>
> -m
>
> --
> + Matt J. Avitable: Senior Systems Analyst, Richweb, Inc.
> + Richweb.com: Providing Internet-Based Business Solutions since 1995
> + (804) 747.8592 x 109
>
>
| |
| Randal L. Schwartz 2007-04-28, 6:58 pm |
| >>>>> "Pierre" == Pierre Mariani <frenchyp@gmail.com> writes:
Pierre> I want to run it on several variables.
Pierre> I have the following code that:
Pierre> - builds an array of references on the variables,
Pierre> - calls the function on the content of the reference,
Pierre> - set the content of the reference to the result of the function.
Why do you have a bunch of scalars that all need the same operation
performed on them? Perhaps they really belonged together as some part
of a data structure in the first place.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
|
|
|
|
|