PeterKaagman has asked for the wisdom of the Perl Monks concerning the following question:

Hi there monks,

I've got a Dancer2 app logging in to azure using the Dancer2::plugin::auth::oauth. Works like a dream. Gives me a session with all sorts of information about the user. In YAML for now, so I can inspect what I have.

Among all that information are the roles the user has. Something you can configure in the app registration on Azure. Works! I can see the information in Vim. Looks something like this in the YAML file:

oauth: azuread: login_info: roles: - Medewerkers - etm

The file is a lot longer offcourse, deleted all that.

As far as I know session->read() loads in the session (from whatever format) into a hash. When I do:

my $session_data = session->read('oauth'); say "Roles:"; print Dumper $$session_data{azuread}{login_info}{roles};

I get on the console:

Roles: $VAR1 = [ 'Medewerkers', 'etm' ];

To me it looks like I'm dumping an array reference. So the session hash contains arrays?

But no matter what I do (and I'm sure I did not do enough) I cannot access the individual values of that array. I kinda expected that something like print $$session_data{azuread}{login_info}{roles}[0] would work. Tried it in all sorts of variations. It confuses me to the bone.

What am I doing wrong? What is the way to read those individual values?

Peter

Replies are listed 'Best First'.
Re: Reading session data
by hippo (Archbishop) on Jun 29, 2023 at 14:01 UTC

    I rarely use the old $$ syntax these days so I would do this:

    use strict; use warnings; use Data::Dumper; my $session_data = { azuread => { login_info => { roles => [ 'Medewerkers', 'etm' ] } } }; print Dumper $$session_data{azuread}{login_info}{roles}; # Like you ha +d print $session_data->{azuread}{login_info}{roles}[0] . "\n";

    It just makes the dereferencing easier to me. See also perldsc for more general info on this.


    🦛

      I rarely use the old $$ syntax these days

      It's amazing how quickly we change.

      I used to always use the 'old' syntax on the rare occasion that I attempted to use references. That was until a few people in The Monastery explained references in a way that made them finally click, and someone showed me the 'modern' syntax. I now use references regularly and always use the modern syntax.

      Recently I looked at a bit of my own code from a while ago and it took me a while to work out what was going on thanks to $$!

      hippo - you say you rarely use the old syntax. That implies that occasionally you do. Is there any situation where the 'old' syntax is preferable or even required?

        Is there any situation where the 'old' syntax is preferable or even required?

        It is not required for hashrefs like this but obviously you can't use the normal arrow to dereference things where there are no components. So, if you have a scalar reference the only ways to dereference that are with a $$ or using postfix dereference. In such situations I much prefer the $$ for clarity. In fact I've just tried this example to illustrate and it won't even compile with the postfix deref line uncommented (error is $* is no longer supported as of Perl 5.30).

        #!/usr/bin/env perl use strict; use warnings; use feature 'say'; my $foo = 'some string'; my $ref = \$foo; say "Deref with \$\$: $$ref"; # Uncomment next line for compilation error - why? #say "Postfix deref: $ref->$*";

        Perhaps someone who likes/uses postfix deref can explain where the compilation error comes from and how to fix it. As for me, I'm quite happy with $$ in these situations.

        See also I use postfix dereferencing ... for various comments on how wonderful/terrible postfix dereferencing is.


        🦛

        G'day Bod,

        It hadn't occurred to me when reading earlier posts referring to "old syntax", but your use of "modern syntax" made me wonder how much older $$hashref{key} was compared to $hashref->{key}.

        The oldest Perl version available via the online "Perldoc Browser" is for "Perl 5.005". Poking around in various parts of that (perlop, perldsc, and others) I see both forms being used without any mention of one being newer. I'm happy to be proven wrong, but I rather suspect that both have been available since Perl 5.000.

        Without the arrow (dereferencing) operator, it's easy to make mistakes, especially with complex data structures. This is discussed in "5.005: perlref: Using References"; this information is retained in "5.36.1: perlref: Using References".

        Except in the simplest of cases, I'll always prefer the $hashref->{key} form, as I find it both easier to read and less error-prone. I can't think of any situation where the $$hashref{key} form is "required".

        In closing, it's probably worth noting "Postfix Dereference Syntax" and "Postfix Reference Slicing". These are newer syntaxes. I prefer them; I acknowledge that others don't. There's an example of the former in my reply to the OP.

        — Ken

      Old syntax :D Must be getting old. But then again, I do remember the introduction of Turbo Pascal (with objects). Or was it called Borland Pascal at that time already :D

      But... Thanks, that did actually works. Funny thing is that even the $$ syntax works just fine. Don't really know how I was goofing yesterday.

Re: Reading session data
by kcott (Archbishop) on Jun 30, 2023 at 08:27 UTC

    G'day Peter,

    From "Re^2: Reading session data":

    "Old syntax :D Must be getting old."

    Newer syntax:

    $ perl -E ' use v5.36; use YAML::XS; my $yaml = Load(<<~\EOY); oauth: azuread: login_info: roles: - Medewerkers - etm EOY my $session_data = $yaml->{oauth}; say for $session_data->{azuread}{login_info}{roles}->@*; ' Medewerkers etm

    — Ken

      Correct me if I'm wrong, but using a YAML lib would only work whenever I use YAML for my sessions. Which is not good practice in a production env as I understand. The session should be agnostic to the format in which it is stored.

        Your example data used YAML; I used an appropriate module to get that data into a Perl data structure.

        My point, however, was not about YAML; it was in relation to old and new syntax.

        hippo had already shown how to get a single array element:

        $session_data->{azuread}{login_info}{roles}[0]

        I showed a newer syntax for getting the entire array:

        $session_data->{azuread}{login_info}{roles}->@*

        Your post resulted in further discussion of old/new syntax. It was an interesting conversation; so, thanks for that.

        — Ken