# closures and bank account objects in perl

# pointers and dereferencing:
my $x = 5;
my $px = \$x; # sets pointer to $x
$$px *=2;
print $px, " holds ", $$px, "\n";

# functions 
sub sw 
{ my $tmp = $_[0];
  $_[0] = $_[1];
  $_[1] = $tmp;
}
my ($x,$y) = (2,3);
sw($x,$y);
print $x, " and ", $y, "\n";  # Perl is call by reference  (int &x in C++)
sw($x+1,$y*2);
print $x, " and ", $y, "\n";  # doesn't change this time, of course

# pointers to functions
# K =lambda x.lambda y.x:

my $K0 = sub{ $_[0]};  # wrong, not curried
my $K = sub { my $x = $_[0];
              sub { $x }};
print $K->(1)->(2), "\n";    #prints 1

# closures

sub makeaccum
{
    my $val = $_[0];    # what if $my is changed to local?
    sub { $val += $_[0]; $val }
}

my $a1 = makeaccum(0);
my $a2 = makeaccum(0);
print $a1->(2), $a1->(2), $a2->(1), "\n";  # prints 241
# change "my $val$ to "local $val" and see what happens (not responsible)
# local really means global

################### bank accounts

sub makeaccount
{
    my $balance = 0;
    my $deposit = sub {  $balance += $_[0] };
    my $withdraw = sub { $balance -= $_[0] };
    my $inquiry = sub {$balance};
    my $interface = sub
    {
	my $req = $_[0];
	if ($req eq "inquiry") { return $inquiry->() }
	if ($req eq "withdraw") { return $withdraw }
	if ($req eq "deposit") { return $deposit }	
    };
    $interface  # returns interface
}

my $myaccount = makeaccount();
$myaccount->("deposit")->(500);
$myaccount->("withdraw")->(-5000000);
print $myaccount->("inquiry"), "\n";

sub betteraccount  # subclass in perl?
{
    my $super = makeaccount();  
}
