Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re^2: Dereferencing in blessed object

by Bod (Parson)
on Feb 25, 2021 at 23:16 UTC ( [id://11128810]=note: print w/replies, xml ) Need Help??


in reply to Re: Dereferencing in blessed object
in thread Dereferencing in blessed object

the only reason why your output seems to be correct is that you are dereferencing the $vars hash-ref from the closure

Oh!
Yes, changing the variable name in the subroutine 'breaks' it as expected...now I understand why the different bits of seemingly identical code behave differently! Thanks Rolf.

$vars->{'test'}; instead of $$vars{test}

I did have $vars->{'test'}; in there at one point whilst testing it.
Why is this preferable to $$vars{test}?

Replies are listed 'Best First'.
Re^3: Dereferencing in blessed object
by LanX (Saint) on Feb 26, 2021 at 00:33 UTC
    Both are legal syntax, the overwhelming mainstream tends to $vars->{'test'} probably since PBP.

    So many might have problems reading the other form.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

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.

      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.

        ... 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)

Re^3: Dereferencing in blessed object
by hippo (Bishop) 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.


    🦛

      "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.

      > 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}} ?

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        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.


        🦛

        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}.

Re^3: Dereferencing in blessed object
by bliako (Monsignor) 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

      > Performance-wise I don't think there is a difference (OSX 10.13 and perl 5.28.3):

      That would be surprsing, it's compiled to the same op-code.

      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>

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        Good point!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11128810]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (6)
As of 2024-04-16 09:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found