#!/bin/perl # bank accounts in perl # there's another way of doing oop in perl - involving packages and # something called "bless". I'm not using that - I'm using perl's # more fundamental capabilities to build oop from scratch, like in scheme # in perl, "scalar" variables which include things like integers and # pointers, are always prefixed with a $. # in perl, "sub" means lambda. Instead of specifying the formal parameters # like in other languages, the parameters are always in an array, which # can be accessed inside the function body as $_[0], $_[1], etc ... # The entire array can be referred to as @_ # A perl function body always returns the last expression it evaluates. # "my" in perl is equivalent to "let" in scheme. # in perl, to apply a function that's returned from another function call, # we can use one of two forms. Assume that $f, $g, and $h are all # pointers to functions. The following are equivalent # &{&$f($g)}($h) and $f->($g)->($h) # both expressions are equivalent to ((f g) h) in scheme. The -> # operator is not the same as the -> in C/C++, but it's similar: # it dereferences a pointer, which in the case of Perl, can be a function. # Goto this link to learn more: # http://iis1.cps.unizar.es/Oreilly/perl/advprog/ch04_01.htm sub newaccount { my $balance = $_[0]; my $inquiry = sub { $balance }; my $deposit = sub { $balance = $balance + $_[0]; }; my $chargefee = sub { $balance -= 3; }; my $withdraw = sub { $balance = $balance - $_[0]; &$chargefee(); }; # return interface function: sub { my $method = $_[0]; # requested method if ($method eq withdraw) { return $withdraw; } if ($method eq deposit) { return $deposit; } if ($method eq inquiry) { return &$inquiry(); } else { die "error"; } } } my $myaccount = &newaccount(500); # the & is actually optional here. my $youraccount = &newaccount(800); my $balance = 50; $myaccount->(withdraw)->(30); # ((myaccount 'withdraw) 30) &{&$youraccount(deposit)}(70); # alternate syntax print "my balance is ", $myaccount->(inquiry), "\n"; print "your balance is ", $youraccount->(inquiry), "\n";