References - problem understanding them

J

Jürgen Herz

Hi,

currently I'm trying to understand references. I've read perltut.pod and
perlreftut.pod but still don't know why does this works:

my $content = test();
for (keys %{$content})
{ print "$_: ",$content->{$_},"\n" }

sub test
{
my %content = (one => "eins", two => "zwei");
return \%content;
}

I'd expect accessing the hash in main doesn't work because it doesn't
exist anymore outside of test(), just the pointer to that gone hash.

I guess I'm wrong in understanding references as pointers like they are
in C. But what are they then?

Regards,
Jürgen
 
D

David Squire

Jürgen Herz said:
Hi,

currently I'm trying to understand references. I've read perltut.pod and
perlreftut.pod but still don't know why does this works:

missing:

use strict;
use warnings;

(though in fact your code is fine w.r.t. both of them)
my $content = test();
for (keys %{$content})
{ print "$_: ",$content->{$_},"\n" }

sub test
{
my %content = (one => "eins", two => "zwei");
return \%content;
}

I'd expect accessing the hash in main doesn't work because it doesn't
exist anymore outside of test(), just the pointer to that gone hash.

OK. I take it you were expecting this code *not* to work, and are
surprised that it did? That's a change from most questions around here :)
I guess I'm wrong in understanding references as pointers like they are
in C. But what are they then?

I don't know the details of how references are implemented in Perl, but
they are more than just a bare pointer (i.e. integer) like that you
would get in C.

The reason that your example works is that Perl is a garbage-collected
language (unlike C), and many garbage-collected languages maintain
counts of references to chunks of memory that are allocated. The memory
is only freed when the reference count goes to zero. Since your sub
returns a reference to the hash created within it, that hash sticks
around so long as the reference exists.


DS
 
J

Jürgen Exner

Jürgen Herz said:
Hi,

currently I'm trying to understand references. I've read perltut.pod
and perlreftut.pod but still don't know why does this works:

my $content = test();
for (keys %{$content})
{ print "$_: ",$content->{$_},"\n" }

sub test
{
my %content = (one => "eins", two => "zwei");
return \%content;
}

I'd expect accessing the hash in main doesn't work because it doesn't
exist anymore outside of test(), just the pointer to that gone hash.

What is gone after the sub is the _name_ %content. But the object behind
that name still exists. There is still a reference pointing to the object
and therefore the perl garbage collector does not recycle that object yet.
I guess I'm wrong in understanding references as pointers like they
are in C. But what are they then?

They are references. And they have very little in common with pointers in C.
Actually they are much easier to understand if you don't have the burden of
previous C knowledge.

jue
 
X

xhoster

Jürgen_Herz said:
Hi,

currently I'm trying to understand references. I've read perltut.pod and

AFAIK, there is no perltut. Have you read perlref?
perlreftut.pod but still don't know why does this works:

my $content = test();
for (keys %{$content})
{ print "$_: ",$content->{$_},"\n" }

sub test
{
my %content = (one => "eins", two => "zwei");
return \%content;
}

I'd expect accessing the hash in main doesn't work because it doesn't
exist anymore outside of test(), just the pointer to that gone hash.

Garbage collection is explained in the 2nd paragraph (v.5.8.8) of
the "description" section of perlref.

Xho
 
K

Klaus

Jürgen Herz said:
Hi,

currently I'm trying to understand references. I've read perltut.pod and
perlreftut.pod but still don't know why does this works:

my $content = test();
for (keys %{$content})
{ print "$_: ",$content->{$_},"\n" }

sub test
{
my %content = (one => "eins", two => "zwei");
return \%content;
}

I'd expect accessing the hash in main doesn't work because it doesn't
exist anymore outside of test(), just the pointer to that gone hash.

I guess I'm wrong in understanding references as pointers like they are
in C. But what are they then?

There is some explanation in perlsub (although it is not obvious to
find)

-------------------------------------------------
"Persistent Private Variables"

Just because a lexical variable is lexically (also called statically)
scoped to its enclosing block, eval, or do FILE, this doesn't mean that
within a function it works like a C static. It normally works more like
a C auto, but with implicit garbage collection.

Unlike local variables in C or C++, Perl's lexical variables don't
necessarily get recycled just because their scope has exited. If
something more permanent is still aware of the lexical, it will stick
around. So long as something else references a lexical, that lexical
won't be freed--which is as it should be. You wouldn't want memory
being free until you were done using it, or kept around once you were
done. Automatic garbage collection takes care of this for you.

[...]
-------------------------------------------------
 
A

Aaron Sherman

Jürgen Herz said:
I'd expect accessing the hash in main doesn't work because it doesn't
exist anymore outside of test(), just the pointer to that gone hash.

I guess I'm wrong in understanding references as pointers like they are
in C. But what are they then?

People will often tell you C pointers and Perl references aren't the
same thing in response to a question like that, but IMHO that's a
terrible thing to tell a C programmer.

In reality they're the same thing, but what you should not do is
confuse lexically scoped variables with stack-allocated variables in C.
You essentially have no access to the stack at all in Perl. The "Perl
stack" is malloced memory, and items allocated on it are freed when
they are no longer referenced. By creating a reference to your
lexically scoped hash, you asked Perl not to release it.

Hope that helps, one C programmer to another.
 
M

Matt Garrish

Dr.Ruud said:
xhoster: schreef:

ISHM perlreftut.

ITYM ITHM? Or is this some concoction of "I'm Sure He Meant", which is
just a guess after staring at for some time. It would be so much easier
to just write what is intended.

(Not to single you out on this particular pet peeve of mine except for
the fact I couldn't decipher this one, but it is annoying in general to
have to look these things up when one isn't hip to the comings and
goings of acronyms.)

Matt
 
J

Jürgen Herz

AFAIK, there is no perltut. Have you read perlref?

I meant perlref. Yes, I've read it, but not really understood - as I fear.

Garbage collection is explained in the 2nd paragraph (v.5.8.8) of
the "description" section of perlref.

Hm, explained - yes and no. Now I know how it works, I understand that
paragraph - but not before. And still I think "automatically freeing the
thing referred to when its reference count goes to zero" doesn't
implicate it's *not* freed as long a reference to it exists.

Thank you,
Jürgen
 
J

Jürgen Herz

David said:
missing:

use strict;
use warnings;

No, not missing. I just let them out here in order to make the example
shorter. I guess that was to well-meant.
OK. I take it you were expecting this code *not* to work, and are
surprised that it did? That's a change from most questions around here :)

:)
Yes, you're right. I often go the way of writing code that I'd expect
not to work in order to be sure I've understood all aspects. Which I
didn't here.
The reason that your example works is that Perl is a garbage-collected
language (unlike C), and many garbage-collected languages maintain
counts of references to chunks of memory that are allocated. The memory
is only freed when the reference count goes to zero. Since your sub
returns a reference to the hash created within it, that hash sticks
around so long as the reference exists.

Thank you, now I see why it works like it does.

Regards,
Jürgen
 
J

Jürgen Herz

Klaus said:
There is some explanation in perlsub (although it is not obvious to
find)

[...]

Uh yes, that's the answer to why that works.

But I still have a bad feeling doing that. So is it considered good (or
bad) style relying on this behaviour? Though it seems to be guaranteed
and should always work, maybe it's on some "List of things better not to
do" because of something like code comprehensibility.

Thank you,
Jürgen
 
J

Jürgen Herz

Aaron said:
In reality they're the same thing, but what you should not do is
confuse lexically scoped variables with stack-allocated variables in C.
You essentially have no access to the stack at all in Perl. The "Perl
stack" is malloced memory, and items allocated on it are freed when
they are no longer referenced. By creating a reference to your
lexically scoped hash, you asked Perl not to release it.

Hope that helps, one C programmer to another.

Indeed that helped. Not references itself are different but the system
of variable allocation in Perl at all.

Thanks,
Jürgen
 
D

Dr.Ruud

Matt Garrish schreef:
Dr.Ruud:

ITYM ITHM? Or is this some concoction of "I'm Sure He Meant", which is
just a guess after staring at for some time. It would be so much
easier to just write what is intended.

It was meant as funny. Not everybody knows even what 'AFAIK' means. My
'S' was 'suppose(d)'.

(Not to single you out on this particular pet peeve of mine except for
the fact I couldn't decipher this one, but it is annoying in general
to have to look these things up when one isn't hip to the comings and
goings of acronyms.)


It's OK. (old knowledge?)
 
K

Klaus

Jürgen Herz said:
Klaus said:
There is some explanation in perlsub (although it is not obvious to
find)

[...]

Uh yes, that's the answer to why that works.

But I still have a bad feeling doing that.

I can understand this, I had the same bad feeling when I started perl
programming. But after several years, I now have a good feeling about
that.
So is it considered good (or bad) style relying on this behaviour?

Personally, I consider this a good style.
Though it seems to be guaranteed and should always work,

There are thousands of CPAN modules which rely heavily on garbage
collection, and they work fine...

....but yes, the garbage collector itself is written by humans, and
humans can make mistakes, but I believe that the human who wrote the
garbage collector makes much less mistakes than I would make, if I
wrote my own code to collect garbage.
maybe it's on some "List of things better not to do" because of
something like code comprehensibility.

Not having to worry about garbage collection in the actual code
improves code comprehensibility.
 
A

anno4000

Klaus said:
Jürgen Herz wrote:
[...]

...but yes, the garbage collector itself is written by humans, and
humans can make mistakes, but I believe that the human who wrote the
garbage collector makes much less mistakes than I would make, if I
wrote my own code to collect garbage.

The garbage collector proper is relatively safe, it's a compact bit
of code that's well debugged. It's rather the maintenance of the
refcount that's error-prone. That happens all over the perl code
(and in XS modules) whenever the default behavior isn't good enough,
which is often. Symptoms are memory leaks when the refcount is too
high and segfaults or entirely bizarre behavior when it is too low.
This must be carefully debugged if perl is to keep its promise that
references are automatically collected and never dangle.

Anno
 
J

Jürgen Exner

Jürgen Herz said:
Indeed that helped. Not references itself are different

Sorry, but I strongly disagree. Pointers in C are memory addresses,
something that otherwise you find in assembler. You can manipulate them, you
can add or subtract to the address, etc, etc.
A reference in Perl is an _abstract_, well, reference to one concrete
object. You cannot change it, you cannot manipulate it, you cannot create it
or destroy it. On an implementation level it may be implemented as a C
pointer, but it could just as well be an index into some variable list or
whatever. As a Perl programmer you don't know and you don't care.
but the system
of variable allocation in Perl at all.

Not really. Perl and C are actually quite similar. Had you said that
_memory_ allocation and management is different, then yes, because C forces
the programmer to implement memory management manually while Perl does it
automatically. There is not new(), malloc(), or free() in Perl.

jue
 
X

xhoster

Jürgen_Herz said:
Klaus said:
There is some explanation in perlsub (although it is not obvious to
find)

[...]

Uh yes, that's the answer to why that works.

But I still have a bad feeling doing that. So is it considered good (or
bad) style relying on this behaviour?

It is excellent style to rely on it. And it isn't like there is a choice.
Pure Perl has no user-accessible malloc or free.

Though it seems to be guaranteed
and should always work, maybe it's on some "List of things better not to
do" because of something like code comprehensibility.

What alternative would you propose?

Xho
 
J

Jürgen Herz

What alternative would you propose?

I'm far from proposing anything. But using plain hash would also work at
least in my example:

my %content2 = test2();
for (keys %content2)
{ print "$_: ",$content2{$_},"\n" }

sub test2
{
my %content2 = (one => "eins", two => "zwei");
return %content2;
}

Jürgen
 
D

David Squire

Jürgen Herz said:
I'm far from proposing anything. But using plain hash would also work at
least in my example:

my %content2 = test2();
for (keys %content2)
{ print "$_: ",$content2{$_},"\n" }

sub test2
{
my %content2 = (one => "eins", two => "zwei");
return %content2;
}


Sure, this will work, but the entire hash gets copied when the sub
returns. For large data structures this can be very inefficient. Passing
around references is much more memory and time efficient for large and
complex data structures.


DS
 
U

Uri Guttman

x> It is excellent style to rely on it. And it isn't like there is a choice.
x> Pure Perl has no user-accessible malloc or free.


x> What alternative would you propose?

there is another style choice. returning a ref to a lexical array/hash
may be confusing but returning an anon array/hash could be less
confusing. so instead of

my @array ;

return \@array ;

do

my $aref = [] ;

return $aref ;

they do the exact same thing but it is clearer code IMO to explicitly
create and return an anon array (or hash). not that i haven't done the
former in some cases but i lean to doing the latter.

the only downside to the $aref version would be how you stuff it. you
have to deref it with ->[] or @{} where in the former case you can do
the slightly simpler direct access to the array.

so here is the choice: cleaner looking return of a ref vs cleaner
access to the array in the sub.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top