Using Closures Instead of Objects
Problem
You want records with private state, behavior, and identity, but you don’t want to learn object-oriented programming to accomplish this.
Solution
Write a function that returns (by reference) a hash of code references. These code references are all closures created in the same scope, so when they execute, they’ll all share the same set of bindings to private variables.
Discussion
Because a closure is a binding of code and data, it can implement what might be thought of as an object.
Here’s an example that creates and returns a hash of anonymous
functions. mkcounter
takes an argument of a seed
counter and returns a hash reference that you can use to manipulate
the counter indirectly.
$c1 = mkcounter(20); $c2 = mkcounter(77); printf "next c1: %d\n", $c1->{NEXT}->(); # 21 printf "next c2: %d\n", $c2->{NEXT}->(); # 78 printf "next c1: %d\n", $c1->{NEXT}->(); # 22 printf "last c1: %d\n", $c1->{PREV}->(); # 21 printf "old c2: %d\n", $c2->{RESET}->(); # 77
The code values in the hash references in $c1
and
$c2
maintain their own separate state.
Here’s how to set that up:
sub mkcounter { my $count = shift; my $start = $count; my $bundle = { "NEXT" => sub { return ++$count }, "PREV" => sub { return --$count }, "GET" => sub { return $count }, "SET" => sub { $count = shift }, "BUMP" => sub { $count += shift }, "RESET" => sub { $count = $start }, }; $bundle->{"LAST"} = $bundle->{"PREV"}; return $bundle; }
Because the lexical variables used by the closures ...
Get Perl Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.