Hi Kenneth,

Welcome aboard (for the nth time)!

The replies on this thread have been helpful, but they haven’t really addressed 
the underlying issue, which is that there’s subscripting, then there’s 
dereferencing. I’ll try to keep my explanation brief, but first a solution:

$confused = [
    bless({
        Id => [
            '01tC0000003udXAIAY',
            '01tC0000003udXAIAY'
        ],
        type => 'Product2'
    }, 'sObject')
];

# strictly speaking, this is the way to do it
$way1 = ${ ${ ${ $confused }[0] }{Id} }[0];

# a cleaner way to do it
$way2 = $confused->[0]->{Id}->[0];

# an even cleaner way to do it
$way3 = $confused->[0]{Id}[1];

print $_, "\n" for $way1, $way2, $way3;

# okay, let’s pretend you want all the ids
@ids = @{ $confused->[0]{Id} };

print $_, “\n” for @ids;

The first thing to realize is that data structure (hash/array) references, or 
any kind of reference for that matter, is stored in a scalar. I’m sure you 
realize this. So:

@array = qw(foo bar boo baz);
$array_ref = \@array;
print “$_\n” for @{ $array_ref }; # prints all the strings in the dereferenced 
$array_ref

But then there’s dereferencing context. In general, dereference syntax is:
[SIGIL]{ $scalar_container }

So:
%{ $hashref }
@{ $arrayref }
${ scalar_ref }

And when retrieving from a data structure, you can specify whether you want a 
slice or a singular value:
@values = @{ $arrayref }; # or, @$arrayref
$count = @{ $arrayref }; # or, @$arrayref
$single_val = ${ $arrayref }[0]; # or $$arrayref[0], or $arrayref->[0]
@one_val_slice = @{ $arrayref }[0]; # or @$arrayref[0], or ( $arrayref->[0] )
@three_val_slice = @{ $arrayref }[0..2]; # or @$arrayref[0..2]

Fundamentally, arrays and hashes can only hold scalar values. All a hash ref or 
array ref is, is a scalar value that acts like a remote control, shortcut, or 
pointer to a multiple value data structure. Other languages hide the 
“reference” concept behind the interface, but Perl is pretty explicit about it.

What it boils down to, is that whenever you retrieve a value from a data 
structure, it’s going to be a scalar: either a string, a number, or a reference 
of some sort. Then if what you’ve gotten is a reference, and you want to get 
values out of it, you need to dereference that, as I’ve shown in the last 
example ( [SIGIL]{ $ref }, etc. ). $way1 above shows explicitly the chain of 
dereferencing that happens as you pull values out of a data structure, level by 
level. It’s not pretty, but it gives you a good idea of what’s going on: 
dereference an array ref to get to a hash ref; dereference a hash ref to get to 
an array ref; dereference that array ref to get to its first, second value, etc.

Fortunately there’s syntactic sugar: the -> operator (see $way2). The -> arrow 
dereferences the reference you use it on, then you subscript to the right of it 
to tell perl which value you want out. Just remember, you always get back a 
scalar, (string, num, or ref), so what you get back needs to be dereferenced if 
it’s some kind of container.

That’s nice, but it’s not that nice, so Perl goes a step further with nested 
dereferencing (see $way3). The rule is this: if you’ve already dereferenced 
with an arrow and a subscript, subsequent subscripts are assumed to dereference 
the value they operate on. This is a very good thing. It makes handling nested 
data structures way easier.

Okay one more thing before I wrap up, and this one’s for free. If you want to 
get multiple values out of a nested data structure you got using pointer 
syntax, you need to wrap the whole thing in a dereference operator. This 
follows from:
1. $some->{really}{deeply}{nested}{array}
2. @values = @{ $hashref }{‘I’, ‘want’, ‘these’, ‘keys’} # or if it’s an array: 
@{ $arrayref }[4..10]

Therefore:
@slicy = @{ $some->{really}{deeply}{nested}{array} }[2..17];
print “$_\n” for @slicy;

All things considered, this isn’t bad. As a practice, I stick with way 3 for 
retrieval, then dereference if I need slices. This makes for cleaner code.

Other languages make things like this easier to pick up, but I think Perl’s 
really nice in the long run because you can think explicitly in terms of 
references (like you can in C). Other dynamic, high-level languages don’t give 
you this kind of freedom.

I suggest reading up on references again:
https://docs.google.com/viewer?url=http%3A%2F%2Fblob.perl.org%2Fbooks%2Fbeginning-perl%2F3145_Chap07.pdf
 
<https://docs.google.com/viewer?url=http://blob.perl.org/books/beginning-perl/3145_Chap07.pdf>

Thanks and happy Perling!

Aaron

> On Apr 13, 2016, at 6:29 PM, Kenneth Wolcott <kennethwolc...@gmail.com> wrote:
> 
> Hi;
> 
>  I have the following output from Data::Dumper and I want to extract
> the first string that the "Id" name points to.
> 
> $VAR1 = [
>          bless( {
>                   'Id' => [
>                           '01tC0000003udXAIAY',
>                           '01tC0000003udXAIAY'
>                         ],
>                   'type' => 'Product2'
>                 }, 'sObject' )
>        ];
> 
>  So if the data structure is contained in a Perl variable called
> $data, then I think that this is a reference to a hash.
> 
>  So I need to do something like "@{$data}" to get to the hash.
> 
>  But I want the "Id" element of the hash so I want something like
> @{$data}->{'Id'}
> 
>  But that's the array, so what about ${@{$data}->{'Id'}}[0]
> 
>  But that isn't right either.
> 
>  I'm either getting an undefined reference to a hash error or not a
> scalar reference error.
> 
> Thanks,
> Ken Wolcott
> 
> -- 
> To unsubscribe, e-mail: beginners-unsubscr...@perl.org
> For additional commands, e-mail: beginners-h...@perl.org
> http://learn.perl.org/
> 
> 

Reply via email to