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 <[email protected]> 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: [email protected]
> For additional commands, e-mail: [email protected]
> http://learn.perl.org/
>
>