Scalar::Util::weaken says:
NOTE: Copying a weak reference creates a normal, strong, reference.
I can't understand why Perl handle it this way. In my applications, I use
weaken
to break cycles. Sometimes i have to weaken references that would be already weak if Perl wouldn't act this way.
Anytime a pointer variable points to an object, that object has an owner and will stay alive. This is known as a strong reference. A variable can optionally not take ownership of an object that it points to. A variable that does not take ownership of an object is known as a weak reference.
A Weak reference is a reference that does not protect a referenced object from collection by GC. i.e. garbage collects when no Strong or Soft refs. A Phantom reference is a reference to an object is phantomly referenced after it has been finalized, but before its allocated memory has been reclaimed.
According to Apple's docs: “Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization.”
A reference to an object is any object pointer or property that lets you reach the object. There are two types of object reference: Strong references, which keep an object “alive” in memory. Weak references, which have no effect on the lifetime of a referenced object.
Any time you copy a reference into a new variable, the reference count is incremented. This is true when copying a weak or strong reference.
my $obj = {}; # 1 reference to {} stored in $obj
my $copy = $obj; # 2 references
weaken $obj; # 1 reference
at this point, if $copy
goes out of scope, the reference count will fall to zero, and the memory will be freed. Now assume the following code:
my $newref = $obj; # 2 references
undef $copy; # 1 reference
If Perl preserved the weak reference in $newref
, then the hash would be unexpectedly dealocated when $copy
was cleared. This would break the expectation that when you copy a reference, it will at least stick around as long as the copy.
In short, if weak references persisted across an assignment, it would force you to litter your code with myriad weakness checks, and would require some other way to unweaken a variable, all to avoid the inevitable variable suicide issues.
I think this is an encapsulation issue. If a third party library uses weak refs internally my code should not be expected to know ahead of time that when I make a copy of a reference that it might suddenly disappear on me. The usual expectation in Perl is that a ref will remain valid as long as it exists. When you call weaken
you basically have promised that you will take the needed steps to check that the reference is still valid before you use it.
As a second reason the interface to weaken a strong copy of a weak ref is fairly strait forward.
my $new_ref = $old_ref; if (isweak($old_ref)) { weaken($new_ref); }
The code to do the same to get a strong ref if a weak ref created a weak ref is a bit more complicated.
my $new_ref;
if (ref($old_ref) eq 'ARRAY') {
$new_ref = \@{$old_ref};
}
elsif (ref($old_ref) eq 'HASH') {
$new_ref = \%{$old_ref};
}
elsif (.....
If you know the ref can only be one type you can save the if
/elsif
cascade and simply do the deref-reref, but it's still harder to judge why you dereferenced just to take a new reference. The next maintainer will try to 'fix' your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With