home *** CD-ROM | disk | FTP | other *** search
- ArmBob v.1.02 Tutorial 3 GCW 06/06/94
-
- Accounts 2
- ------------
- Now we look at Bob:main.account. In main, the variable 'account_no' is
- used to count the number of accounts that have been created. The
- maximum is given by the variable 'enough'. The statement
-
- client = newvector(enough);
-
- creates a vector called 'client' with enough components. The term
- "vector" is used, rather than "array", for two reasons. First,arrays
- in Basic, C, Pascal, etc are homogeneous - all their components must
- have the same type. Vectors are inhomogeneous - their components
- can have quite different types. Second, one is often tempted to think
- of arrays as occupying a sequential block of memory. This would be
- misleading for vectors. Strings in ArmBob are closer to arrays in this
- sense. In fact vectors correspond more closely with structs of pointers
- in C, or with records in Pascal.
-
- The components of an n-component vector v are denoted
-
- v[0], v[1], .... v[n-1]
-
- It is legitimate for a vector to be a component of itself! When a vector
- is first created, its components all have the value nil.
-
- The components of client are to be the instance objects of the class
- account. The function 'banner' informs the user of the services that the
- Toy Town Bank can offer. It produces the output
-
- Welcome to the Toy Town Bank.
-
- 0 Quit
- 1 Open an account
- 2 Make a withdrawal or deposit
- 3 Get a statement
- 4 Change your password
-
- Press one of the above numbers then press RETURN.
-
- Then follows the main loop of the program
-
- while ((i = input()) != "0") /* Top level interaction loop */
- { ...... }
-
- which gets input from the user with the function 'input', and responds
- accordingly with a switch statement. Those new to C should realise
- that in C, and ArmBob, assignments, like
-
- i = input()
-
- are actually expressions, which return a value as well as produce a
- side-effect, and so this value can be part of a larger expression
-
- (i = input()) != "0"
-
- This is not the case in Basic. Remember that Basic uses '=' with two
- meanings - assignment and test for equality. In C, and ArmBob, these
- two uses are distinguished. Assignment uses '=', test for equality uses
- '=='. Another catch for the Basic programmer unused to C lurks in
- the switch statement. In Basic's CASE ... WHEN .... ENDCASE construction
- execution automatically jumps to after the ENDCASE from the end of
- the code following a WHEN condition. On the other hand in C's, and
- ArmBob's, switch (..){ .... case .... } construction, execution does
- NOT automatically jump to after the closing brace, unless specifically
- directed to do so with a 'break;' statement. Forgetting the 'break;'
- is a frequent source of error.
-
- The switch statement in main is used to dispatch execution to various
- alternative functions, the first of which is new_account. Note the line
-
- amount = val(input());
-
- The 'input' function always produces a string. The function 'val'
- converts a string to a number, as far as possible. The next line
-
- client[account_no++] = new account(amount,name);
-
- uses the post-increment operator '++'. This is an example of a unary
- assignment operator. The effect of this one line is equivalent to
-
- client[account_no] = new account(amount,name);
- account_no = account_no + 1;
-
- The vector 'client' is being used to store all the accounts in a single
- structure.
-
- Note that we have functions 'withdraw', 'statement', 'change_password'
- despite the fact that these are names of methods for the 'account'
- class. There is no clash, because methods are private to the class
- they belong to. All these functions use the function 'get_account'
- which uses the 'has_owner' method to find which accounts, if any, have
- an owner 'name'. It returns 'the_account', so that the operator
-
- client[the_account]->
-
- can be applied to the appropriate method to do what has been requested.
-
- The heart of get_account is the search for the account owned by 'name':
-
- while ((the_account<account_no)
- && !(client[the_account]->has_owner(name)))
- the_account++;
-
- The && operator corresponds to Basic's AND, but it has an important
- advantage - it is lazy! Compare these two programs, the first in Basic,
- the second in ArmBob.
-
- The Basic version:
-
- REM AND is strict
- IF FNf AND FNg THEN PRINT "yes" ELSE PRINT "no"
- END
-
- DEF FNf
- PRINT "<<Evaluating f>>"
- = 0
-
- DEF FNg
- PRINT "<<Evaluating g>>"
- = 0
-
- The ArmBob version:
-
- /* && is NOT strict */
- main()
- {
- if ( f() && g() ) print("yes\n");
- else print("no\n");
- }
-
- f()
- {
- print("<<Evaluating f>>\n");
- return 0;
- }
-
- g()
- {
- print("<<Evaluating g>>\n");
- return 0;
- }
-
- The Basic program produces as output
-
- <<Evaluating f>>
- <<Evaluating g>>
- no
-
- whereas the ArmBob program produces
-
- <<Evaluating f>>
- no
-
- In other words, && does not bother to evaluate its right hand argument
- when it finds that its left hand argument is zero, whereas AND always
- evaluates both. This is smart of && and dumb of AND because you often
- need, as here in get_account, to test two conditions where error-free
- evaluation of the second condition is contingent upon the success of
- the first condition. This usually happens with vectors or arrays, where
- the first condition checks that an index lies within its bounds, and
- if it is, the second condition checks some expression involving the
- component given by the index.
-
- In the same way C's and ArmBob's || is lazy where Basic's OR is strict.
- If the left hand argument of || is true, the right hand argument does
- not get evaluated.
-
-