--- name: weak references --- # Weak references Perl tracks object lifetime with **reference counting**. Every value knows how many references point at it; when the count drops to zero, the value is freed. This works well for tree-shaped data, where references flow one way, parent to child. It fails for **cycles**, where a chain of references eventually points back at something earlier in the chain. The cycle's members keep each other alive even when nothing outside the cycle refers to them any more. A **weak reference** is a reference that does not increment the referent's reference count. It lets you point at something without keeping it alive. Weak references are Perl's standard answer to reference cycles. ## How a cycle leaks Consider a doubly-linked list node that holds both `next` and `prev` references: ```perl sub new_node { my ($value) = @_; return { value => $value, next => undef, prev => undef }; } my $a = new_node('A'); my $b = new_node('B'); $a->{next} = $b; $b->{prev} = $a; ``` `$a` and `$b` each have a reference count of 2: - `$a` is referenced by the lexical `$a` **and** by `$b->{prev}`. - `$b` is referenced by the lexical `$b` **and** by `$a->{next}`. When the lexicals go out of scope, their contribution drops: - `$a` drops to count 1 (only `$b->{prev}` left). - `$b` drops to count 1 (only `$a->{next}` left). Neither reaches zero. Both nodes are unreachable from anywhere in your program, yet they keep each other alive for the life of the interpreter. That's a leak. ## Fixing the leak with `weaken` `Scalar::Util::weaken` turns an existing reference into a weak one. The reference still works for dereferencing; it just doesn't count toward keeping the target alive. The standard pattern: whichever direction you consider "back-pointer" or "parent pointer", make **that** one weak. ```perl use Scalar::Util qw(weaken); my $a = new_node('A'); my $b = new_node('B'); $a->{next} = $b; $b->{prev} = $a; weaken $b->{prev}; # the back-pointer ``` Now `$a`'s reference count stays at 1 (only the lexical `$a` contributes; `$b->{prev}` is weak and does not count). When `$a` goes out of scope, `$a` is freed — and because freeing `$a` drops `$b->{next}`, `$b` is freed too. The whole structure collapses. ## When a weak reference becomes undef If the referent is freed while a weak reference still exists, the weak reference **automatically becomes `undef`**. You never see a dangling pointer: ```perl use Scalar::Util qw(weaken); my $target = { name => 'alive' }; my $weak = $target; weaken $weak; print defined $weak ? "yes\n" : "no\n"; # yes undef $target; # last strong ref gone print defined $weak ? "yes\n" : "no\n"; # no ``` `defined $weak` is the standard way to check whether the target is still there. See [`defined`](../../p5/core/perlfunc/defined). ## Where weak references belong The rule: use a weak reference for the "non-owning" pointer in any pair of references that would otherwise cycle. - **Doubly-linked list.** `next` owns; `prev` is weak. - **Parent/child tree with parent pointers.** `children` owns; `parent` on each child is weak. - **Observer pattern.** The subject holds weak references to its observers; observers hold strong references to the subject. When an observer drops its reference, it goes away; the subject's entry for it turns to `undef` and can be swept. - **Caches that shouldn't keep entries alive.** A cache whose values are weak references does not extend the lifetime of the cached objects. ## `isweak` — inspecting a reference `Scalar::Util::isweak` tells you whether a given scalar holds a weak reference: ```perl use Scalar::Util qw(weaken isweak); my $x = { k => 1 }; my $y = $x; print isweak($y) ? "weak\n" : "strong\n"; # strong weaken $y; print isweak($y) ? "weak\n" : "strong\n"; # weak ``` Useful mostly when debugging a lifetime problem. Production code rarely branches on `isweak`. ## Common mistakes - **Weakening the wrong end.** Weakening the "forward" pointer (the one that owns the successor) frees the successor immediately, before you ever use it. Weak goes on the **back-pointer**. - **Weakening a lexical.** `weaken $ref` where `$ref` is a fresh lexical referencing `$target` makes the lexical weak. If nothing else holds a strong reference to `$target`, it vanishes at the next statement and `$ref` becomes `undef`. Weak references belong in data-structure slots, not typically in local lexicals. - **Assuming weak references are automatic.** Perl does **not** detect cycles and weaken them for you. You have to opt in. ## Beyond Scalar::Util `Scalar::Util` ships with Perl; it is always available. For more elaborate needs — `WeakRef`, `Hash::Util::FieldHash` — reach for CPAN. For ordinary code, `weaken` is all you need. ## Where to go next You've finished the references tutorial. Good next reads: - The [`ref`](../../p5/core/perlfunc/ref) reference page — the full list of strings it returns, including blessed-object cases. - [`bless`](../../p5/core/perlfunc/bless) — how a plain hash reference becomes an object of a specific class. - The object-orientation tutorial, once you're ready for classes built on top of the references you now understand.