MathGroup Archive 2002

[Date Index] [Thread Index] [Author Index]

Search the Archive

RE: Programming language difficulties.

  • To: mathgroup at smc.vnet.net
  • Subject: [mg38420] RE: [mg38382] Programming language difficulties.
  • From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
  • Date: Sat, 14 Dec 2002 03:20:12 -0500 (EST)
  • Sender: owner-wri-mathgroup at wolfram.com

>-----Original Message-----
>From: Oliver Ruebenkoenig [mailto:ruebenko at donne.imtek.uni-freiburg.de]
To: mathgroup at smc.vnet.net
>Sent: Friday, December 13, 2002 10:10 AM
>To: mathgroup at smc.vnet.net
>Subject: [mg38420] [mg38382] Programming language difficulties.
>
>
>Hi again Mathgroup ;-)
>
>This is a programming example from the wizard book chapter 3.
>( http://mitpress.mit.edu/sicp/full-text/book/book.html )
>
>Consider the following: 
>
>withdraw := Evaluate[
>    Module[ { balance = 100 },
>      Function[ amount,
>        If[ balance >= amount,
>          balance -= amount; balance,
>          Print[ "Insufficient Funds" ]
>          ]
>        ]
>      ]
>    ]
>
>In[2]:= withdraw [ 60 ]
>
>Out[2]= 40
>
>In[2]:= withdraw[ 60 ]
>Insufficient Funds
>
>The question now is, can I in Mathematica write a function 
>that takes as
>argument the balance, so that I do not have to use the fixed balance =
>100. Note that in first example balance is _not_ present in the global
>context. 
>
>My idea was the following:
>
>secondWithdraw[ initBalance_ ] := Evaluate[
>    Module[ { balance = initBalance },
>      Function[ amount,
>        If[ balance >= amount,
>          balance -= amount; balance,
>          Print[ "Insufficient Funds" ]
>          ]
>        ]
>      ]
>    ]
>
>In[7]:= W1:=secondWithdraw[ 100 ]
>
>In[8]:= W1[ 60 ] 
>Out[8]= If[initBalance >= 60, balance$2 -= 60; balance$2, 
>>    Print[Insufficient Funds]]
>
>So this however does not work. I _assume_ that Evaluate hits to early.
>The evaluation of balance >= amount to initBalance >= amount is too
>early. Is this the problem? How can I circumvent it?
>
>I'd be glad for any insights you might have.
>
>
>Oliver Ruebenkoenig, <ruebenko at imtek.de>
>   Phone: ++49 +761 203 7293
>
>

Oliver,

you'r quite right, dispense with that Evaluate:
 
In[5]:= withdraw2[initBalance_] := 
  Module[{balance = initBalance}, 
    Function[amount, 
      If[balance >= amount, balance -= amount; balance, 
        Print["Insufficient Funds"]]]]

In[11]:= W1 = withdraw2[100];

In[12]:= balance$21
Out[12]= 100

In[13]:= W1[60]
Out[13]= 40

In[14]:= W1[60]
>From In[14]:=
"Insufficient Funds"

The example from the wizard book, in fact is no good at all, just construed
to bewilder little children. Your idea to create an account, an individual
object, is much better. However other methods should be defined, and the
constructor given a different name.

Here is something containing several "member functions":
 
In[177]:= Remove[createAccount]
In[178]:=
createAccount /: Set[thisAccount_, createAccount[initial_:1 ]] :=
  (thisAccount = Module[{account, key = Random[Integer, {0, 10^12}]},
          With[{key = key},
            account[Balance] :=
              
              SequenceForm[account[key], 
                "\[ThinSpace]\[InvisibleComma]\[InvisibleComma]", EUR];
            account[key] = initial;
            account[Withdraw] = (If[account[key] >= #, (account[key] -=
#)EUR,
                    Print["Insufficient Funds"]; $Failed]) &;
            account[Deposit] = (account[key] += #;
                  If[account[key] > 10^6, Print["Beware of Taxes!"]]; 
                  account[key]EUR) &;
            account]];)

In[179]:= myAccount = createAccount[]

	-- this calls the constructor with default initial balance 
	   (a donation from my bank), no output is given

In[180]:= ?myAccount
Global`myAccount

myAccount = account$154

	-- that's the object created

In[181]:= ?account$154
....
	-- you see what's behind the scene

In[182]:= myAccount[Balance]
Out[182]= 1 EUR

	-- method Balance shows the initial donation

In[183]:= myAccount[Deposit][60]
Out[183]= 61 EUR

In[184]:= myAccount[Balance]
Out[184]= 61 EUR

In[185]:= myAccount[Withdraw][50]
Out[185]= 11 EUR

In[186]:= myAccount[Withdraw][50]
>From In[186]:=
"Insufficient Funds"
Out[186]= $Failed

In[187]:= myAccount[Deposit][10^7]
>From In[187]:=
"Beware of Taxes!"
Out[187]= 10000011 EUR


Perhaps it is better to move the methods to a class (and just fix the
parameters):

In[206]:= Remove[createAccount, Balance, Withdraw, Deposit]
In[207]:=
createAccount /: Set[thisAccount_, createAccount[initial_:1 ]] :=
  (thisAccount = Module[{account, key = Random[Integer, {0, 10^12}]},
          account[key] = initial;
          With[{key = key}, account[Balance] := Balance[account, key]];
          account[Withdraw] = Withdraw[account, key];
          account[Deposit] = Deposit[account, key];
          account];)
In[212]:=
Balance[account_, key_] := 
  SequenceForm[account[key], "\[ThinSpace]", EUR]

In[213]:=
Withdraw[account_, key_][amount_] := 
   (If[account[key] >= amount, (account[key] -= amount)EUR,
    Print["Insufficient Funds"]; $Failed])

In[214]:=
Deposit[account_, key_][amount_] := 
   (account[key] += amount;
    If[account[key] > 10^6, Print["Beware of Taxes!"]]; account[key]EUR)

The key isn't necessary, consider it as a password (from the bank not from
you! and it doesn't matter if someone else has the same password) Of course
we have to hide Information, however I couldn't succeed as my definition...

Evaluate[account] /: Information[account, ___] := "gotcha!";

...prevented Information["account$154"] but not 
Information["account$154", LongForm -> True] or
Information["account$154", LongForm -> False]

...wasn't effective. The explanation for that certainly is quite
complicated, so I have to state: with Mathematica you can reach for any
money (and any password for that matter)!

--
Hartmut Wolf



  • Prev by Date: AW: Pasting tables into Excel
  • Next by Date: Speed Comparison
  • Previous by thread: Re: Programming language difficulties.
  • Next by thread: Re: Programming language difficulties.