Re^3: Dereferencing in blessed object
by LanX (Saint) on Feb 26, 2021 at 00:33 UTC
|
| [reply] [d/l] |
Re^3: Dereferencing in blessed object
by eyepopslikeamosquito (Archbishop) on Feb 26, 2021 at 03:55 UTC
|
Oh! Yes, changing the variable name in the subroutine 'breaks' it as expected
To avoid wasting time chasing silly mistakes like these in future, I suggest you always --
as a matter of routine habit -- order your file with functions first and mainline at the end.
An alternative is to leave the mainline first but put a bare block around it, to ensure
mainline global variables don't accidentally leak into the subroutines defined below.
| [reply] |
|
|
I suggest you always -- as a matter of routine habit -- order your file with functions first and mainline at the end
Whilst that makes sense, it somehow feels wrong.
Probably because I have always written code with the subroutines at the end. I recall it being a bit of a revelation when I realised that it wasn't compulsory to have them at the end!
An alternative is to leave the mainline first but put a bare block around it
That seems very sensible. It's also something that can be applied to existing code relatively easily.
| [reply] |
|
|
... I have always written code with the subroutines at the end
Curiously, I've always done the reverse, perhaps because in C you must declare a function
before calling it, and I wanted to avoid the tedious duplication of
writing forward declarations for my locally defined C functions called from main.
Even in Perl, order matters, for example:
use strict;
use warnings;
# mainline--------------------------
mygreeting "world";
# subroutines ----------------------
sub mygreeting {
my $salutation = shift;
print "hello $salutation\n";
}
fails to compile:
String found where operator expected at g1.pl line 5, near "mygreeting
+ "world""
(Do you need to predeclare mygreeting?)
syntax error at g1.pl line 5, near "mygreeting "world""
because the compiler is yet to see the mygreeting subroutine definition.
Though you can fix with the compiler's predeclare mygreeting suggestion,
or by hoisting the mygreeting subroutine definition to the top of the file,
I prefer to avoid these sorts of compilation glitches simply by following
a simple rule: "always call user-defined subroutines with parens".
Here the parens give the compiler a strong hint that mygreeting is a subroutine,
even though it is yet to parse its definition.
That is, this compilation error is easily remedied simply by adding parens to the call:
mygreeting("world");
As a matter of style, some folks find the code easier to read when user-defined functions
are always called with parens and built-in functions are always called without parens ...
I see Perl Best Practices
endorses this style via:
- Don’t use unnecessary parentheses for builtins and ‘honorary’ builtins (item 4)
- Call subroutines with parentheses but without a leading & (item 113)
| [reply] [d/l] [select] |
|
|
|
|
Re^3: Dereferencing in blessed object
by hippo (Archbishop) on Feb 26, 2021 at 09:39 UTC
|
Why is this preferable to $$vars{test}?
I don't see objectively why it would be, TBH. If you start getting into deeper structures then the increasing levels of syntax needed to deal with the $$foo{bar} equivalents is going to get messy. For a simple hash though there's little difference.
Personally I do use the arrow operator as it (subjectively) stands out more clearly to me in an eye-parse. But I do not quote hash keys (whether in references or otherwise) unless necessary. If I see code like $vars->{'test'} it makes me pause and wonder why the key is quoted.
Whatever you decide to do, make a plan and stick to it. Having your own coding standard, at least within one project, will be a benefit. Inconsistency is the bug's friend.
| [reply] [d/l] [select] |
|
|
"Personally I do use the arrow operator as it (subjectively) stands out more clearly to me in an eye-parse."
Yep, me too.
I like being able to understand code at a very quick glance, and at a quick glance, I would (and do) see $$var{thing} as a hash, not a hash reference. $var->{thing} is very unambiguous and doesn't require a second look, ever.
Because scalar references are so infrequently used, I would expect to have to look twice at a variable with the double $$ to understand why the author has used one. An in-memory variable-based file is one example, and is a special case that often does require a bit more than just a glance.
| [reply] [d/l] [select] |
|
|
> If you start getting into deeper structures then the increasing levels of syntax needed to deal with the $$foo{bar} equivalents is going to get messy.
Could you give an example? I hope you are not referring to redundant -> arrows at deeper levels.
> But I do not quote hash keys
Neither do I, I just copy pasted from B::Deparse's output.
edit
> I don't see objectively why it would be,
Like Bliako said, I have trouble parsing precedence, and I don't think it's only a matter training.
can you immediately tell if $$x{key} means ${$x}{key} or ${$x{key}} ?
| [reply] [d/l] |
|
|
Could you give an example? I hope you are not referring to redundant -> arrows at deeper levels.
Quite the opposite, actually. By "equivalents" I was meaning the same syntax but for different data. eg. if we have $foo = { bar => [4, 5, 6] } and we want to operate on the array we can use @{$foo->{bar}} which is fine or @{$$foo{bar}} which, while valid, is a bit syntax heavy for my taste. (I like sigils but anything which starts off @{$$ is just asking to be clarified)
can you immediately tell if $$x{key} means ${$x}{key} or ${$x{key}} ?
I can but that's (a) from experience and (b) because sigils bind most tightly (as you said: precedence). It would not be a surprise to find that someone new to Perl would struggle with this too.
Don't get me wrong - I agree with the presumed majority who use the arrow most/all of the time. However I do recognise it is a subjective choice and don't criticise others for avoiding it.
| [reply] [d/l] [select] |
|
|
|
|
can you immediately tell if $$x{key} means ${$x}{key} or ${$x{key}} ?
Personally I've just memorized this special case and yes, when I see $$x{key} or $$y[2] I just know this means $x->{key} or $y->[2]. I sometimes find it a bit nicer because of the parallels bewteen e.g. my %x = ( key => 42 ); print $x{key}; and my $x = { key => 42 }; print $$x{key}, but I also completely understand that people prefer $x->{key}, and I often use this style myself, for example I prefer $self->{key} over $$self{key}.
| [reply] [d/l] [select] |
|
|
Re^3: Dereferencing in blessed object
by bliako (Abbot) on Feb 26, 2021 at 12:25 UTC
|
$$vars{'test'} is a visual pain for me because of the split millisecond where I ask myself about precedence. OTH the -> in $vars->{'test'} dates back to at least C where is used in exactly the same way and context.
Performance-wise I don't think there is a difference (OSX 10.13 and perl 5.28.3):
use Benchmark qw( cmpthese );
cmpthese(-5, {
deref => 'use strict; use warnings; my $x = { map { $_ => rand
+ } 1..50 };
$x->{$_} = $_ for 1..100',
none => 'use strict; use warnings; my $x = { map { $_ => rand
+ } 1..50 };
$$x{$_} = $_ for 1..100'
});
Rate deref none
deref 12483/s -- -1%
none 12611/s 1% --
Rate none deref
none 11938/s -- -0%
deref 11967/s 0% --
Or,
use Benchmark qw( cmpthese );
cmpthese(-5, {
deref => 'use strict; use warnings;
srand 42;
my $x = { map { rand() => rand() } 1..50 };
srand 42;
$x->{rand()} = rand() for 1..100',
none => 'use strict; use warnings;
srand 42;
my $x = { map { rand() => rand() } 1..50 };
srand 42;
$$x{rand()} = rand() for 1..100'
});
For benchmarks see also: https://stackoverflow.com/questions/18984323/how-expensive-is-it-to-dereference-an-array-ref-in-perl
bw, bliako
| [reply] [d/l] [select] |
|
|
C:\WINDOWS\System32>perl -MO=Deparse -e"$$x{key}"
$x->{'key'};
-e syntax OK
C:\WINDOWS\System32>perl -MO=Concise -e"$$x{key}"
4 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter v ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- <1> ex-helem vK/2 ->4
3 <+> multideref($x->{"key"}) vK ->4
- <0> ex-gv s ->3
-e syntax OK
C:\WINDOWS\System32>perl -MO=Concise -e"$x->{key}"
4 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter v ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- <1> ex-helem vK/2 ->4
3 <+> multideref($x->{"key"}) vK ->4
- <0> ex-gv s ->3
-e syntax OK
C:\WINDOWS\System32>
| [reply] [d/l] |
|
|
| [reply] |