Re: Relative Merits of References
by ikegami (Patriarch) on May 11, 2006 at 14:33 UTC
|
I see some differences.
-
my $h = {'name' => 'value', ...};
creates two variables (a hash and a reference to it), while
my %h = ('name' => 'value', ...);
creates only the hash.
-
my $h = {'name' => 'value', ...};
requires dereferencing to access the hash, while you might need to create references to
my %h = ('name' => 'value', ...);
to use it.
-
It is less obvious in
my $h = {'name' => 'value', ...};
than in
my %h = ('name' => 'value', ...);
that was are dealing with a hash because the hash sigil is not used in the former.
-
However, all of the above are rather inconsequential. The real difference is that it would have been much less work to switch to
my $h = {'name' => 'value', ...};
rather than to
my %h = ('name' => 'value', ...);
since the rest of the code was expecting a reference to a hash.
| [reply] [d/l] [select] |
Re: Relative Merits of References
by Hue-Bond (Priest) on May 11, 2006 at 13:51 UTC
|
References are useful to pass data to functions. Using references, you pass a single scalar to the function, so perl doesn't have to copy the entire thing. Update: And they are also useful to create complex data structures. A hash of hashes is really a hash of references to hashes.
| [reply] [d/l] |
|
Indeed references are just great! OTOH I have also seen very bad examples of programs abusing references in every place. I remeber this guy who kept passing stuff around referencing and dereferencing all the time, and in fact at one point he got stuck! Had he used @arrays and %hashes in the first place, is code would have been much KISSer.
| [reply] |
|
Thanks David
Understood, when passing by reference is needed, having a reference around is handy, but then creating one using
\%h
is not exactly complicated. I'm wondering if there are any reasons to choose one over the other - this example doesn't seem to qualify.
pbeckingham - typist, perishable vertebrate.
| [reply] [d/l] |
Re: Relative Merits of References
by blazar (Canon) on May 11, 2006 at 14:03 UTC
|
I was recently tasked with 'porting' a large body of code from Perl 5.6 to 5.8.x. The following construct (simplified), which was legal in 5.6 is no longer so:
my %$h = ('name' => 'value', ...);
...
print $h->{'name'};
Was it legal? I can understand my %$h to work as a symref. But then why should $h->{'name'} be correct? Or else does this mean that
my %$h = ('name' => 'value', ...);
# was "expanded" to
my $h = {'name' => 'value', ...};
or something like that? If so, then I agree on such behaviour to have been removed, as you declare variables, not variable dereferences that autovivify the reference. That would be too much of a dwimmery, doing what in fact I shouldn't mean. | [reply] [d/l] [select] |
Re: Relative Merits of References
by Zaxo (Archbishop) on May 11, 2006 at 14:20 UTC
|
I think that the alternative is better than yours for a pretty simple reason. With it, you don't need to find and edit out the dereference op for every use of the hash. Only one line of code needs to change.
context
context
-my %$h = ('name' => 'value', ...);
+my $h = {'name' => 'value', ...};
context
print $h->{'name'};
| [reply] [d/l] |
Re: Relative Merits of References
by YuckFoo (Abbot) on May 11, 2006 at 19:50 UTC
|
Since almost all hashes and arrays I make end up getting passed to
subroutines, I usually just create them as refs. This has the
(slight) benefit having a consistent point of dereference in mainline
code and subroutine code instead of having to remember to move the
arrow around. Also foo($this) looks nicer that foo(\%that).
RefFoo
#!/usr/bin/perl
use strict;
my %rgbs = (
yellow => { r => 0xff, b => 0, g => 0xff, },
magenta => { r => 0xff, b => 0xff, g => 0, },
);
print "$rgbs{yellow}->{r}\n";
foo(\%rgbs);
sub foo {
my $rgbs = shift;
print "$rgbs->{yellow}{r}\n";
}
| [reply] [d/l] |
Re: Relative Merits of References
by wfsp (Abbot) on May 11, 2006 at 14:17 UTC
|
It would make a difference if you wanted to pass two hashes to a sub.
#!/usr/bin/perl
use strict;
use warnings;
my $h1 = {
one => 1,
two => 2,
};
my $h2 = {
three => 3,
four => 4,
};
my_sub($h1, $h2);
sub my_sub {
my ($h1, $h2) = @_;
print "$_ $h1->{$_}\n" for keys %{$h1};
print "$_ $h2->{$_}\n" for keys %{$h2};
}
In these circumstances refs are, imo, the only way to go. :-) | [reply] [d/l] |
|
#!/usr/bin/perl
use strict;
use warnings;
my %h1 = (
one => 1,
two => 2,
);
my %h2 = (
three => 3,
four => 4,
);
my_sub(\%h1, \%h2);
sub my_sub {
my ($ref1, $ref2) = @_;
my %h1 = %{$ref1};
my %h2 = %{$ref2};
# Or "my %h1 = %{(shift)};" will work too, but I don't really like it.
print "$_ $h1{$_}\n" for keys %h1;
print "$_ $h2{$_}\n" for keys %h2;
}
if you want to keep the hash. This is really the only way to go :) | [reply] [d/l] |
|
my ($r1, $r2) = @_;
...
print "$_ $h1{$_}\n" for keys %$r1;
print "$_ $h2{$_}\n" for keys %$r2;
Update:Thanks again David, yes, I meant:
print "$_ $r1->{$_}\n" for keys %$r1;
print "$_ $r2->{$_}\n" for keys %$r2;
pbeckingham - typist, perishable vertebrate.
| [reply] [d/l] [select] |
|
Re: Relative Merits of References
by johngg (Canon) on May 11, 2006 at 14:39 UTC
|
#use strict;
#use warnings;
$h = "fred";
%$h = (name => "Jim", age => 34);
print $h->{name}, "\n";
print $fred{age}, "\n";
produces Jim
34
Switching on strict like this
use strict;
use warnings;
our %fred;
my $h = "fred";
%$h = (name => "Jim", age => 34);
print $h->{name}, "\n";
print $fred{age}, "\n";
produces Can't use string ("fred") as a HASH ref while "strict refs" in use at
+pbeck2 line 8.
because use strict; objects to soft references. Only by switching strict off for the duration of a code block can you use soft references.
use strict;
use warnings;
our %fred;
my $h = "fred";
{
no strict q(refs);
%$h = (name => "Jim", age => 34);
print $h->{name}, "\n";
}
print $fred{age}, "\n";
produces Jim
34
I hope this clarifies what might be happening with your "illegal" code. Cheers, JohnGG | [reply] [d/l] [select] |
Re: Relative Merits of References
by clinton (Priest) on May 11, 2006 at 14:19 UTC
|
Why do you think that that construct is illegal? I tried this code in perl 5.8.7 and it works without any warnings.
use strict;
use warnings;
use Data::Dumper;
my $a;
%$a=(a=>1,b=>2);
print Dumper($a);
And it prints
$VAR1 = {
'a' => 1,
'b' => 2
};
UPDATE : I see now that the illegal part was the "my %$h" part rather than the assigment part. So that could have been changed simply by splitting the declaration to a separate line, or by changing the list to a {}.
However it seems an odd way to do it when you could just say :
$a={a=>1,b=>2};
I benchmarked the two versions, and the first %$a=() is 50% slower than the second ($a={}).
Regarding the difference between $h{name} versus $h->{name}, there is a slight speed difference (10%), because the second version first needs to dereference $h before doing the lookup, but it is so blazingly fast that I wouldn't worry about it. (Tested on a small hash - not sure for bigger hashes)
Rather just use whatever is easier to read, as there are bound to be other bottlenecks that make much more difference to your code's performance.
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
Yep, I missed the significance of the my %$h = .... I'm thinking back now to dimly remembered exam advice from more than thirty years ago, "Read the question carefully before answering." I'll try to pause for thought next time.Cheers, JohnGG
| [reply] [d/l] |
|
%$a={a=>1, b=>2};
I would need to check but it looks like it does the assignment of the hash in $a and then copies it into a hash (%) which is then thrown away as it is unassigned.
I don't have a copy of 5.6 available but it would be interesting to see if my %$a assigned both %a and $a via the glob. In 5.8 it appears to do as suggested earlier.
UnderMine
| [reply] |
Re: Relative Merits of References
by zerogeek (Monk) on May 12, 2006 at 07:56 UTC
|
I just wanted to thank all of you, especially pbeckingham, for nodes (did I use that term correctly?) like this one.
Being new to Perl - I'm only up to Ch13 in the Llama book - these are the types of posts that are really helpful to read through. It is very interesting and helpful to see all the different solutions to the same problem.
Additionally, the comments regarding WHY you chose one way over another are useful.
Again-
Keep 'em coming. I'm feeling smarter every day! | [reply] |
|
If you're going to be maintaining older code, I recommend Perl Medic be on your reading list, as well.
| [reply] |
Keep it consistent
by kbrint (Sexton) on May 12, 2006 at 12:48 UTC
|
If I need to pass it by reference to many places, then I create it as a reference as well. That way, code in the scope where it's created looks the same as elsewhere; both can use $h->{key}. Otherwise, in the scope where it's created you use $h{key}, and everywhere else you use $h->{key}
| [reply] [d/l] [select] |