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}->(); # 77The 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 ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access