home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Falcon 030 Power 2
/
F030_POWER2.iso
/
ST_STE
/
MAGS
/
ICTARI03.ARJ
/
ictari.03
/
GFA
/
TUTORIAL
/
GFA3.TXT
< prev
next >
Wrap
Text File
|
1989-07-29
|
38KB
|
761 lines
Subject: GFA Tutorial, Month One
By: James Collett (Professor)
A Member Of: VIRTUAL INFINITY
Email: s6005146@oxpoly.ac.uk (or s6005146@brookes.ac.uk)
Address: Room N4, L.S.C.Collage, Wheatley, Oxford, OX9 1HX
Mono accnt.: bcc
Introduction To Syntax And Structure
====================================
In the same way 'human' or natural languages have syntax & structure,
computer languages do too; and natural language syntax & structure
provide a good analogy for computer languages:
Syntax is far more than just saying sentences must contain words and
sentences must start with capital letters. It is a complete set of
rules, in theory unambiguous, which can be used to determine whether a
sentence is valid or not. For example "The built a was tamer fortune
blaze by lazy." contains words and starts with a capital but would not
be considered a valid sentence! An example of simple syntax rule would
be sentences may consist of 'determiner + adjective + noun': "The brown
fox."
In a similar way that syntax varies from natural language to natural
language (e.g. English and French), syntax also varies between computer
languages (e.g. GFA Basic and C++). If we want a particular program to
work, we must ensure the syntax is correct.
In the natural language called English, structure is the way that
sentences are fitted together into paragraphs, and paragraphs fitted
together with a heading at the top/etc to form documents, letters, etc.
(Both syntax and structure will be discussed in more detail this
month.)
Variables
=========
Throughout this tutorial I will try to indicate instructions with an
asterisk (*) to distinguish them from information.
* From low res, load GFA Basic and press <escape> for direct mode:
A very important aspect in programming is being able to store and
manipulate numbers and text. Places where data is stored are called
variables but can be thought of as 'draws', where each draw has a label
and a contents. You can think of GFA Basic having an infinite number of
draws (it`s not quite, but it`s a hell of a lot!) and when you first
load the language all these draws are unlabelled and empty.
To label a draw, for example age, and put an age in it type:
* age%=19
To label a new draw, for example surname, and put a name in it type:
* surname$="Professor"
Note that integer (whole number) variables (or 'numerical draws') are
identified with a percentage sign and string variables (or 'text draws')
are identified with a 'dollar sign', which is also called string. I.e.
you would pronounce these two variables 'age percent' and 'surname
string'.
Note also that strings must be enclosed in double quotes ("), this is
not part of the string but indicates where it starts and finishes.
Two simple commands used to manipulate variables are PRINT and INPUT,
note that commands do not have to be entered into GFA in capitals, but
throughout this tutorial I will try to put them in capitals to identify
that they are commands.
PRINT is used to output to the screen, to find out the contents of
the variables (or 'draws') type:
* PRINT age%
* PRINT surname$
INPUT is used to input, from the keyboard, a value (number) or string
into a variable. Try:
* INPUT age%
* INPUT new_value%
GFA should prompt for a number in each case. After entering, type
the following, followed by your name at the prompt:
* INPUT surname$
Note that when you put your age into age% the previous contents are
completely destroyed; similarly for surname$. Check this out by typing:
* PRINT age%
* PRINT surname$
* PRINT new_value%
PRINT can also be used directly with values and strings (text) as
well as with variables ('draw' labels).
Typing long commands every time can be very laborious and most
commands have abbreviations or short hand versions. The abbreviation of
PRINT is simply ?. Try some of the following, using both PRINT and ?:
* ? 7
* ? 7-2
* ? age%+14
* ? "Hi there!!"
* ? "Hi there "+surname$+"!!"
* ? age%+new_value%+2
As well as using plus (+) to return results to screen, it can also be
used to store results as variables. Try this:
* new_value%=age%+3
* ? new_value%
* age%=age%+1
* PRINT age%
* surname$="Hello "+surname$
* ? surname$
Note that + has a different purpose depending on whether being used
with strings or numbers. If you try and use it with a mixture of both
then you will get an error - i.e. GFA syntax rules have been broken!
Instead you must use a semicolon (;) as follows:
* ? surname$;" is ";age%;" years old"
* ? surname$;" will be ";age%+1;" next year"
You can also use minus (-) to subtract, asterisk (*) to multiply and
slash (/) to divide numbers, although obviously not strings! So in
summary:
Strings = Use + to 'add' strings, to screen or a variable
Integers = Use + - * / to manipulate, to screen or a variable
Both = Use ; to 'mix' strings and integers, to screen only
Before we write our first program, note what happens if you try to
put a string in an integer variable (or integer 'draw'), and vise-versa:
* surname$=19
* age%="Professor"
Note also what happens if you try to put a real number (number with
decimal point) into an integer:
* new_value%=-6.54321
* PRINT new_value%
Our First Program
=================
Another note just before we write our first GFA program: if you have
just started programming (maybe today!) I hope you can appreciate, when
you start looking at any sources, you will come across things you
haven`t learned yet and have to take as true or trust the programmer.
I think it is important to show some demo sources as quickly as
possible, thus there maybe one or two lines you`ll just have to trust me
on for the minute!
* Press <escape> to return to the editor and Merge VARIAB_1.LST:
Before we Run (execute) the set of instructions lets manually go
through them (or 'dry-run' them). First of all a message will be
displayed asking for a name and then INPUT surname$ from the keyboard.
After getting age% (presumably in years), it is multiplied by 12 to
convert into months. The program then greets the person, and informs
them of their age (now in months!) before ending. Note that the first
two output lines end with a semicolon but the last output line doesn`t;
if no semicolon is present on the end of a PRINT then GFA will
automatically start a new line (i.e. LF+CR), if you wish to continue on
the same line then you must include a semicolon.
* Run the program by either pressing the appropriate function key or
clicking on the appropriate menu button. Enter a name and age of your
choice. If you don`t trust the output (why not?!?) then, after ending,
goto the direct mode, check the result by multiplying the input age by
12 and return to the editor. Note that the 'run screen', at the point
when execution stopped, appears as the 'backdrop' on direct mode.
* Re-run the program a few times, try to predict what you would expect
to happen if you input a number for the name or string for the age. Try
also inputing negative numbers or real (decimal) numbers as the age.
This program is very simple, but not bad for a first effort! Let`s
try improving things:
* From the editor Merge VARIAB_2.LST:
DO NOT RUN THIS - IT WILL NOT WORK! Note that Merge [which loads an
ASCII source] doesn`t wipe the previous contents. The advantage (or
disadvantage!) of Load [which loads a 'tokenised' source] is it does
wipe the previous contents and starts from scratch. The reason we have
to use Merge, as already discussed, is to make this tutorial compatible
with all versions of GFA.
* From the editor select New to start from scratch, confirm your action
and now Merge VARIAB_2.LST:
I`ve added to this source an initial clear screen, then scraped the
PRINTs and included user-defined prompts with the INPUTs. The GFA
default prompt is a question mark (?). Note a comma is necessary to
separate the optional prompt and variable. Next is the fastest method,
in GFA, to multiply a variable by a value: MUL var,n is about 30% faster
than var=var*n. There are similar commands to ADD, SUB and DIV (all
will be dealt with in detail later).
Moving to the output, after the CHR$ you`ll notice I`ve used
semicolons instead of plus`s to allow 'mixing' of strings and numbers in
a single PRINT statement. CHR$, again to be discussed later, returns
(displays) the character of a given ASCII value. For example to display
an "A", which has ASCII 65, type the following in the direct mode:
* ? CHR$(65)
* ? CHR$(7)
ASCII 10 is LF and leaves a gap on screen. ASCII 7 (above) is BEL
and sounds the ST`s bell.
I personally do not like the standard GFA END command, which brings
up the horrible alert box, and prefer to "finish off" myself by beeping,
waiting for a key press (INP(2)) and returning directly to the editor.
It`s a matter of personal preference and you may wish to beep, flash,
print "Program Terminated" or a whole host of other things to indicate
your own programs have reached their normal ends. As well as END and
EDIT, there is also a STOP command which displays an alert box and
returns to direct mode, STOP does also allow you to continue (if
possible - i.e. stopped in middle) which is occasionally useful.
Note in GFA 3 VOID can be abbreviated to ~. Thus I finish the
majority of my GFA 3 programs with:
PRINT CHR$(7);
~INP(2)
EDIT
VOID (discussed later) is mainly used with numerical functions
(discussed later) to mean you wish to execute or perform a calculation
but not hold the returned result. Sounds strange but very useful, for
example wait for key press but not care which key is pressed.
Comments And Annotation
=======================
* From the editor select New, confirm and Merge COMMENTS.LST:
It is often useful, especially with more complex pieces of source, to
add comments (or remarks) and to annotate lines. GFA provides the
single quota (') for an entire line comment and explanation mark (!) for
annotation on, and after, a line to be executed. The text after the
marker will be ignored during execution and can break every syntax rule
in the book! The convention, however, is to high-light with asterisks
but this depends on your personal preference.
Variable Types
==============
As well as being able to store and manipulate strings (text) and
integers (whole numbers), GFA can also (hopefully obviously!) handle
real numbers. In the same way integers and strings are respectfully
identified with a percentage sign and string (dollar) sign, real numbers
are identified with ... no sign! In summary:
var$ = string (text) variable, contents marked with quotes (")
when assigned to variable
var% = 32 bit integer variable, range approx -2 billion to +2
billion
var = real number, range VERY BIG and VERY ACCURATE
The advantage of using integer over real, where real is not required,
is that of speed - integers are faster that real numbers, but can only
be used if no decimal is needed (e.g. a counter, discussed in more
detail this month).
GFA 3 also offers 16 bit integer (word) and 8 bit integer (byte)
variables, which are even FASTER than a standard integer but with
reduced ranges, as follows. During this tutorial I shall stick with 32
bit integers (long-words) so it is GFA 2 compatible:
var& = 16 bit integer variable, range -32768 to +32767
var| = 8 bit integer variable, range only 0 to 255
Boolean Expressions - Introduction To Decision Making
=====================================================
Another important concept in programming is that of branching, i.e.
coming to a 'junction' and either going one way or the other - no buts
or maybies!
A boolean expression is one that is either TRUE or FALSE, for example
either age% is 99 or it`s not 99, either surname$ is "smith" or it`s not
"smith" - no buts or maybies. Considering numbers for the moment, as
well as testing if a variable or value is identical to another, you can
also test:
> greater than
< less than
>= greater than or equal to
<= less that or equal to
<> greater or less than (i.e. not equal to)
* Goto direct mode and type CLS to clear screen if required:
In GFA, TRUE has the value (or 'is represented by') -1 and FALSE has
the value 0. Try some of the following and try to predict the returned
result (note they don`t have to be entered in capitals):
* ? TRUE * PRINT 7>7
* ? FALSE * ? 7>=7
* ? 2=2 * ? (3+1)=(2*2)
* ? 2=5 * ? 9<=(3+4)
* ? 2<>5 * ? (9<=(3+4))=FALSE
* ? 2<5
(As well as testing if a string is identical to another, there are
other 'string tests', to be discussed in detail next month.)
In GFA, to branch a way dependant on the 'truth' of an expression, we
use IF ... ENDIF and IF .. ELSE .. ENDIF.
* Return to the editor and have a look at BRANCH_1.LST and BRANCH_2.LST
(don`t forget to New before you Merge!)
As well as simple tests (e.g. <> or >=), combinations of tests can be
made using the logic gates: AND, XOR (exclusive or), OR (and/xor) plus
NOT; for example age%<99 AND NOT(surname$="smith"). I am not going to
cover the complete set of 'truths' for all gates (called the 'truth
tables') because they are even more boring than this tutorial (which
does improve next month!) and are fairly straight forward anyway.
*However, I have included a sample source, BRANCH_3.LST, and a truth
table source, TRUTABLE.LST, to have a look at.
You can use the latter if you need the table for a particular
expression, and it is set up for '(NOT P) AND Q' where P and Q represent
simple tests such as age%<99 or surname$="smith". After covering FOR
and NEXT (this month) you`ll be able to add or remove simple test
representatives as required.
Note in GFA 3 an ELSE and IF can compress onto one line (shown
right), thus meaning the second ENDIF and second indent are not needed.
During this tutorial I shall stick with the GFA 2 compatible method
(shown left):
ELSE
IF value%<10 ELSE IF value%<10
PRINT "Number ~~~~ PRINT "Number ~~~~
ELSE ELSE
PRINT "Number ~~~~ PRINT "Number ~~~~
ENDIF ENDIF
ENDIF
Looping - Introduction And FOR ... NEXT Loop
============================================
It is often necessary in programs to repeat a particular part a fixed
number of times, repeat while a condition (boolean expression) is TRUE
or even repeat until one is TRUE. One way of doing this could be to
laboriously enter the part of the source 500 times! The serious
solution is to use a loop, i.e. to tell GFA to 'loop' around the part
either a fixed number of times or in collaboration with a boolean
condition. GFA Basic actually offers no fewer than four 'looping
mechanisms' which allow solutions to be found to any problem where it is
necessary (or might be necessary) to repeat part of a program:
The first and simplest loop, called the FOR ... NEXT loop, uses a
counter to repeat the part a fixed number of times - which could be once
or a million times.
* From a 'clean' editor Merge, look at and Run FORNXT_1.LST:
The loop can be thought of as building a 'table', in this case from 1
to 5 (the maximum count), and each time the loop is executed the next
slot in the table is 'ticked off'. This isn`t quite how it works,
inside the processor, but a good way to think for a simple loop. Note
the value of the counter when you leave the loop, after final execution.
* Look at and Run FORNXT_2.LST, preferably in low res:
It may be necessary to use a far more complex count mechanism or
'STEP' than just 1, 2, 3. For example 0.2, 0.4, 0.6 (STEP 0.2) or -0.5,
-1.0, -1.5 (STEP -0.5). This source is a perfect demonstration of this,
which uses the PLOT command to draw a circle point by point using sine &
cosine waves [note this mathematical source can be replaced with one
line; sine, cosine, PLOT and graphics will be discussed in detail
starting next month]. Note also that speed and angle (theta) need to be
real, the radius(`s) and origin only need to be round to whole number
though.
* Try experimenting with the parameters (or 'control variables'),
now discussed in general:
Parameters
==========
[Going off at a tangent for a few minutes (and nothing directly to do
with looping!) a brief word about parameters.]
Parameters (also called operands) can be best thought of as
'switches' or, as I said before, 'control variables'. In the same way
your TV/monitor has a stack of knobs on it (no innuendoes please!),
anything from a single line or routine upto a procedure (discussed this
month) or complete program can have 'knobs'. For example the parameter
of the line PRINT "Hello" is "Hello" and the parameters of ADD c%,4 are
c% and 4.
If, in a routine or program, you have a size/etc that is constant
(e.g. 4) then you could put 4 everywhere you need it or you could
declare size% as 4 and put that everywhere. If you needed to change it
for some reason, is it easier to change one size% or to search through
the entire source and change all 4`s, hoping you don`t miss any and
don`t change any 4`s which aren`t the size??
Listing all variable parameters together, towards the top of the
program, saves you writing a complex user interface in your utilities at
all and in final programs until the actual 'guts' are written and
tested. (I never put proper user interfaces on my utilities - no need!)
The use of (constant) parameters in programs will become more
apparent with the use of more complex sources.
* Experiment with FORNXT_2.LST`s parameters.
Looping - Continued
===================
* From a 'clean' editor Merge, look at and Run FORNXT_3.LST:
Returning to the FOR ... NEXT loop, GFA also offers a DOWNTO
facility, which is the equivalent to STEP -1 and cannot be used with
other STEPs. Therefore in summary:
If you need STEP -1 then use DOWNTO,
If you need STEP 1 then use TO (without a STEP, 1 is default),
And if you need any other STEP then use TO with a STEP
... obviously making sure you get the mincount and maxcount in the
correct order whichever version you use!
Note the value of the counter when you leave the DOWNTO loop, after
final execution.
* Look back at TRUTABLE.LST, mentioned above in Boolean Expressions.
Figure out how the nested (i.e. one inside another) loops work,
remembering the values of TRUE and FALSE (and not forgetting to New
before Merging.)
The next two loops are the REPEAT ... UNTIL loop and the WHILE ...
WEND (endwhile) loop, which respectfully REPEAT UNTIL a boolean
condition is TRUE and repeat WHILE one is TRUE (i.e. until it`s FALSE).
These are excellent for any situation where you`re waiting for something
to happen or waiting for something to stop happening, for example
waiting for a valid input:
* Look at and Run WHILE.LST:
Typical use of a WHILE loop to repeat input until the variable stops
being invalid. (Note LEN returns the length of a string, functions will
be discussed next month.)
* New, Merge, look at and Run REPEAT_1.LST:
Note this collects the key press (test%) from INP(2), another
function, instead of VOIDing or 'ignoring' it as seen in cases so far.
This loop REPEATs UNTIL test% is ASCII 120, i.e. "x".
The main difference between REPEAT ... UNTIL and WHILE ... WEND is,
as can be seen, the positioning of the boolean test to determine whether
to go around the loop again (or at all). In the REPEAT ... UNTIL loop,
as the test is at the end you will always go around the loop once; if
this isn`t wanted then the loop must be nested inside (placed inside) an
IF ... ENDIF. In the WHILE ... WEND loop, as the test is at the start
the loop will never be executed if it tests FALSE when you first hit the
loop; for example, in WHILE.LST, you enter a valid name/age first time
before the loop.
The final 'loop mechanism' which GFA offers, and many other languages
don`t, is the DO ... LOOP loop. The primary use of this is as an
infinite loop, i.e. once you get in it`s impossible to get out without
taking fatal measures! Sounds strange but useful for both testing
unfinished programs and final programs with no exit (e.g. game or demo).
* After Merging, look at and Run DOLOOP_1.LST:
Once Run, don`t press reset! The way to break out of any GFA program
that appears to have crashed or gone into an infinite loop is to
simultaneously hold down CTRL, ALT and SHIFT. (If this fails for a
crashed GFA program then do reset!) [Note this break facility does not
work with the compiler (discussed later).]
In GFA 3 you can also use DO ... LOOP as a REPEAT ... UNTIL, a WHILE
... WEND, or even a combination of these two:
Unfortunately this is GFA 3 only. If you`re using version 3 then
LOAD DOLOOP_2.GFA, otherwise LOAD DOLOOP_1.BAS. Note when you Load you
don`t have to New first. Load and Save are the conventional way to store
and re-call files, Merge and SaveA are conventionally used for appending
(merging) and for 'inter-compatibility'. To GFA 2 users: DOLOOP_1.BAS
is the same as DOLOOP_1.LST, but I couldn`t not let you try Load! And
if you want to see what your missing you`ll just have to get a copy of
GFA 3!
To users with GFA 3: DOLOOP_2.GFA uses two boolean test
representatives, P and Q, to show a combination of REPEAT ... UNTIL and
WHILE ... WEND. Note, if doing this combination, the tests can be
identical or can be different. In this example, 'P' determines whether
the loop is executed the first time and 'P AND NOT(Q)' is the determiner
after that.
Building Other Loop Combinations
================================
GFA Basic also has an EXIT IF command which can be attached to any
loop, including an 'infinite' DO ... LOOP in GFA 2. It is bad practice
to use this and should be avoided whenever possible, but allows an 'EXIT
IF boolean condition' to be added to DO ... LOOPs and FOR ... NEXTs plus
extra control to be added to REPEAT ... UNTILs and WHILE ... WENDs.
* Merge, look at and Run FORNXT_4.LST:
After placing 120 (ASCII of "x") into key% and displaying the
instructions, this source goes into a STEPped -1 FOR ... NEXT loop,
which counts down the number of attempts left to hit the right key,
using EXIT to 'jump' out the loop should key% be pressed before attempt%
runs out. If the loop is left 'properly' then attempt% will have 'run
out' (i.e. become 0); otherwise, by pressing the EXIT key%, attempt%
will be left 'hanging'.
This source shows one way of combining a FOR ... NEXT and REPEAT ...
UNTIL.
* Merge, look at and Run REPEAT_2.LST:
This does exactly the same job as the previous, but by using a REPEAT
UNTIL and combining attributes from FOR ... NEXT, it handles the
attempt% counter better.
There are *several* methods, even in GFA 2 and without an EXIT IF, to
combine all three mechanisms into one basic loop should it be necessary.
Introduction To Arrays
======================
Moving on, an array is simply a table of variables all of the same
type (e.g. all strings or all reals).
* Goto direct mode and type CLS to clear screen if required:
'Paper tables' or 'manual tables' (e.g. timetable) can be one
dimensional (i.e. just have one column or one row) and can be two
dimensional (i.e. have both rows and columns). In the same way, for the
moment, computerised arrays can be one dimensional or two dimensional.
To create a new one dimension (one column) array with 6 rows
(numbered 0 to 5) type the following (remembering commands don`t need to
be entered in capitals):
* DIM value%(5)
To display the contents of the first 'box' on the table ('box' 0)
simply type the following, the value 0 should be returned:
* PRINT value%(0)
[[NOTE that some versions, as far as I know GFA 3 only, return an
"array index to large" error. If this has happened to you it`s not
because of my tutorial but a minor bug with Direct mode. To fix the bug
simply return to the editor, New to clear, type 'DIM correct%(0)' in the
editor, Run this line, return to direct mode, re-type 'DIM value%(5)'
and continue from there. Please remember even a language as superb as
GFA can only be 99% perfect!]]
Note the contents of all 'boxes' in a new array are initially 0. To
change the contents of the sixth 'box' ('box' 5), use one of the
following just like 'normal' variables:
* value%(5)=22
* INPUT value%(5)
Array elements (or array 'boxes') can be treated just any other
variables. Try some of the following, predict what`s happening:
* value%(0)=3
* value%(1)=8
* ? value%(0)<value%(1)
* INPUT value%(2)
* ? value%(1)+value%(2)
* ? value%(0)*value%(2)
Note, as with variables, when you put a new value into an element the
previous contents are destroyed. Note also that GFA starts counting
rows (and columns) from 0. Therefore if you had a one dimension array
with its last element labelled 9, it has 10 elements in total.
To create a new two dimension array with 3 rows (numbered 0 to 2) and
3 columns (0 to 2, thus 9 elements total) type:
* DIM text$(2,2)
Once again this can be treated as a stack of string variables. Try
the following, once making the comparison between column 0, row 0 and
column 2, row 1 TRUE and once making the result FALSE:
* text$(0,0)="professor"
* INPUT text$(2,1)
* ? text$(0,0)=text$(2,1)
Note what happens if you try to access an element ('box') outside the
defined table`s range or size:
* ? text$(3,4)
(The use and application of arrays will become apparent this month.)
Computerised arrays, unlike 'manual tables', are not restricted to
the 2-D nature of paper and can have three, four, a dosen or more
dimensions if necessary. Here is an example of a 4-D array, which is 3
by 2 by 4 by 3:
* DIM array(2,1,3,2)
This meaningless, 'applicationless' array could be used to store and
manipulate 72 (i.e. 3*2*4*3) real numbers.
Applications Of Arrays (One)
============================
Arrays are potentially useful whenever you have lists or tables of
variables of the same type.
* Return to the editor. Merge and look at ARRAY_1.LST, a trivial
example of array application. By this stage you should be able to
follow an understand a GFA source of this complexity without Running,
using only comments and annotation as aid.
* After 'dry-running' (i.e. manually going through the source), Run it
for real. Experiment with the program parameters and source.
(I shall be returning to array application again this month.)
Procedures
==========
Often in programs, it is useful or necessary to use the same routine
several times, at different points. Procedures not only allow this,
without needing multiple or repeated copies of routines, but also allow
programmers to manage and structure their sources during creation,
testing and implementation.
A procedure is a set of collective instructions, which normally
perform a single simple task, to which you give a label. Humans use
'procedures' as well as computer languages, and such 'human brain
procedures' might be called (labelled) "getting up in a morning",
"making a cup of tea" or "reacting to a fire alarm" - i.e. a set of
instructions which perform a single task. In the same way that 'human
procedures' can be executed (or 'called'), a GFA program can call (i.e.
execute) a procedure.
* Procedure syntax varies slightly between GFA 2 and GFA 3. Either
Load PROCED_1.BAS or PROCED_1.GFA, depending on your version (noting you
don`t have to New), and look at the source:
The main program calls (i.e. runs) a procedure to get all the drinks
and then another procedure to display the drinks. Get_all_drinks in
turn repeatedly calls a procedure to get a single drink, which RETURNs
to get_all_drinks, and that RETURNs to the main program after all the
drinks have been entered. After the last procedure, i.e. show_drinks,
has finished execution it RETURNs to the main program, from which you
finish.
In both GFA 2 and 3, all procedures are listed, in any order, after
the end of the main program and are conventionally separated with gaps.
The syntactical difference is in the calling: in GFA 3 you just use the
procedure label, but in GFA 2 this must be preceded by an 'at' sign (@).
Procedures not only make sources easier to follow, but also allow
programs to be broken down into sections which allows easy testing and
debugging.
As well as using procedures to do *very* specific tasks, it is also
possible to write more 'general' procedures or procedures which still do
one task but offer some freedom in specification. This is achieved by
'giving' the procedure a set of specification when you call it, whether
from the main program or another procedure; or what`s called passing
parameters [i.e. procedure 'control values' - slightly different to
program 'control values'].
* The following source in based on FORNXT_2.LST, if necessary look back
at this source first.
* Preferably in low res, either Load PROCED_2.BAS or PROCED_2.GFA
depending on your GFA version, and look at the source before Running it:
This uses procedure oval to draw a single ellipse to any
specification (i.e. to any origin & radius`s), as seen in FORNXT_2.LST.
It is called oval so as not to conflict with GFA`s own ELLIPSE command
(to be discussed later along with sine, cosine and PLOT).
(Local and global variables will be discussed in a moment). The main
program initially fixes the speed, and then repeatedly calls oval in
order to draw the face.
The angle (theta) is *only* used in oval and not used anywhere else.
It is often useful to indicate such variables as LOCAL to a procedure,
as oppose to the default: global to the *entire* program (i.e. both main
program and all procedures).
Local And Global Variables - A Proper Explanation
=================================================
LOCALising variables also allows several programmers to work on
different parts of the same application or program - the LOCAL variables
used in one procedure won`t interfere with variables used anywhere else.
* From the editor Load PROCED_3, but don`t Run it yet:
You can also LOCAL an already global variable, in which case the
variable will take one (LOCAL) value inside the procedure and another
(global) value in the rest of the program. This is quite a complex
concept if you`ve never done it before, so I shall go through this demo
source (dry-run it) step by step:
First of all variable1, an integer, is assigned the value 5. Before
calling procedure one you are informed of this. Procedure one (after
the main program) then declares variable1 LOCAL, i.e. its value inside
this procedure does not effect its value anywhere else. It is important
to note all LOCAL variables, when declared, initially take the value 0
until assigned another value, in this case 3. After leaving the
procedure and RETURNing to 'the top', variable1 re-takes its global
value, in this case 5. You are informed of this (and the value of
variable2 - dealt with in a moment) before the program finishes.
* Run the program and check this does happen.
* 'Activate' the call to two, but don`t Run it yet:
Procedure two also uses variable1, but the global variable1 with a
value of 5. Its value is incremented to 6, you are informed of this
both before leaving this procedure and when RETURNed to the main
program.
* Re-Run the program and check procedure two.
* 'Activate' the call to three, once again dry-run before doing it 'for
real':
As well as passing values to procedures, variables can also be passed
to procedures; in this case a new variable2, which also must be an
integer. Note variable2 is local to this procedure, and if used in the
rest of the program would maintain its global value on RETURNing.
* Re-Run and check the final procedure.
Thus if you were to pass variable1 from the call, and get passed
variable1 (instead of variable2) in the procedure, changing variable1
locally in the procedure does not effect the global value.
* Check this by modifying procedure three accordingly.
Note also that parameter passing and localising is not just
restricted to integer variables and values, reals and strings can also
be passed and localised in the same way.
Applications Of Arrays (Two)
============================
1-D and 2-D arrays can easily be 'visualised', if necessary, by
thinking of them as 'paper tables'. The following example of array use
shows a good way of 'visualising' a 4-D array for this particular
application.
Imagine you`re the owner of two hotels in London, one coded 'hotel 0'
and other coded 'hotel 1'. Each hotel has 5 floors (grounds, first ...
fourth) and each floor has 16 rooms (1 to 8 down the left corridor and
rooms 9 to 16 down the right corridor). Thus you have 160 rooms in
total (i.e. 2 hotels * 5 floors * 2 corridors * 8 rooms).
A very simple hotel management system (that can`t even handle
advanced bookings!) may need the following three arrays:
DIM surname$(1,4,1,7)
DIM arrive_date$(1,4,1,7)
DIM leave_date$(1,4,1,7)
Note I would treat the arrival and departure dates, for a particular
person in a particular room, as strings and of the form "ddmmyy". For
example 12th May would be "120593". (Note extraction of information
from strings and string <--> integer conversion is covered later.)
The first procedure you would need is one to book somebody in. After
a few months, with people constantly booking, and leaving, this database
will become 'untidy' or 'patchy'. The book_in procedure will have to
search through UNTIL it finds an empty room (OR finds both hotels are
full). After inputing and somehow validating both name and dates, the
procedure can allocate the room to the person, and also possibly work
out their bill.
The other main procedure you would need is one to 'vacate the room'
in the database after the person has paid and is ready to leave. If you
didn`t know the room number and only knew the surname, the program would
have to search through UNTIL it found a match for surname$().
The procedures would then need linking using either a command-driven
or menu-driven system. This simple demo of 'visualising' a multi
dimensional array (for which I haven`t written a source) is *FAR* from
complete as a hotel system and leaves many problems such as how to deal
with advanced bookings or how to deal with several people with the same
surname.
And Finally
===========
I have deliberately set this month`s tutorial at an elementary level
to give anyone a nice, gentle introduction to GFA. I hope you found
some of it (if not most of it!) too easy. Although I won`t actually be
putting GFA through its paces until months 3 and 4, I do intend to move
onto more advanced stuff next month (including my game, LightMaze!) and
hopefully make the tutorial less 'wordy'.
I am not going to include a summary list of everything you should be
able to do after going through this tutorial; but have included both
source and compiled, executable versions of a simple exam grade program,
which includes most of what you should be able to do.
* Load, look at and Run EXAMMARK. Experiment with the source and add
an expansion of your choice for next month`s tutorial.
---END---