Here is an idea:
SetAttributes[account, HoldAll ]
makeAccount[ initBalance_ ] :=
Module[ { balance = initBalance },
account[ balance ]
]
account /: balance[ account[ bal_ ] ] := bal
account /: deposit[ account[ bal_ ], newBal_ ] := ( bal += newBal )
account /: withdraw[ account[ bal_ ], amount_ ] := ( bal -= amount ) /;
amount <= bal
account /: withdraw[ account[ bal_ ], amount_ ] :=
Print[ "Save some cash first" ] /; amount > bal
Format[ acc_account /; ValueQ[ balance[ acc ] ] ] := "-account-"
Then use this as:
a1 = makeAccount[100]
a2 = makeAccount[150]
balance[a1]
100
deposit[a1, 100]
200
balance[a1]
200
balance[a2]
150
This works because of the unique symbol:
FullForm[a1]
Edit:
Here is a version without SetAttributes
makeAccount1[ initBalance_ ] :=
Module[ { balance = initBalance , withdraw, deposit, amount,
dispatch},
withdraw[ amount_ ] :=
Module[ {},
If[ balance >= amount,
balance -= amount; balance,
Print[ "Insufficient funds" ]
]
];
deposit[ amount_ ] :=
Module[ {},
balance += amount;
balance
];
amount[ amount_ ] :=
Module[ {},
balance
];
dispatch[m_] :=
Which[
StringMatchQ[ m, "withdraw" ], withdraw,
StringMatchQ[ m, "deposit" ], deposit,
StringMatchQ[ m, "amount" ], amount,
(* else *)
True, Print["Unknown request -- MAKE_ACCOUNT ", m]
];
Return[ dispatch ];
]
Use as follows:
acc = makeAccount1[ 100 ]
acc2 = makeAccount1[ 200 ]
dispatch$99 dispatch$100
acc[ "withdraw" ][ 10 ]
90
acc2[ "withdraw" ][ 60 ]
140
acc2["amount"][]
140