home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Archive Magazine 1995
/
ARCHIVE95.iso
/
discs
/
pipeline
/
abacus
/
p_line
/
Custom03
/
ReadMe
< prev
next >
Wrap
Text File
|
1992-08-27
|
18KB
|
343 lines
%OP%VS4.13 (28-Apr-92), Gerald L Fitton, R4000 5966 9904 9938
%OP%DP0
%OP%IRY
%OP%PL0
%OP%HM0
%OP%FM0
%OP%BM0
%OP%LM4
%OP%PT1
%OP%PDPipeLine
%OP%WC1022,2262,168,1748,0,0,0,0
%CO:A,72,72%
%C%Custom Functions from the Beginning - Part 3
%C%by Gerald L Fitton
Keywords:
4ProL Custom Function Introduction Decision Validation Fitton
This is the third tutorial article in the series which I hope will help
you with PipeDreamá4's custom functions. The first two articles were
on an earlier PipeLineá4 disc in the directories Custom01 and Custom02.
If you wish to write custom functions then you need to learn '4ProL',
the PipeDreamá4 custom function programming language.
If you have a deep screen mode then it is preferable to use it because
it will make it easier to see substantial parts of the custom function
without losing the document which 'calls' it. If not, then you will
have to use mode 12 and scroll through the documents as is necessary.
I am using the Atomwide VIDC mode 102 with an Eizo 9070S multiscan and
an A540 Archimedes. This monitor-mode combination has a screen depth
of over 50 lines and a screen width of over 130 system font characters
when using PipeDream. Mode 12 is about half that width and depth, a
quarter of the area!
The module DeskModes (in the Mode directory of the 4PL9208 disc) by
David Holden will give you a wider (up to 96 characters) and deeper (up
to 36 rows) screen on a standard resolution monitor. Unless you have
something better then I suggest that you use one of his modes rather
than Mode 12.
Summary of parts 1 and 2
I am calling Colton Software's PipeDreamá4 Programming Language '4ProL'
(until someone comes up with a better name - there is a prize for a
better name).
Designing a new language such as '4ProL' is always a compromise.
The compromise is between:
(a) Including commands which provide the flexibility needed to carry
out complex or intricate processes quickly and
(b) Inherent constraints which encourage those 'good' programming
techniques needed to facilitate debugging and program improvements.
The compromise is to learn a set of conventions (a sub set of the
constraints of the language) which encourage 'good' programming and to
aim to write 'well written' programs. Only after becoming master of
the conventions should you break them knowing that you need speed or
efficiency which can not be achieved by sticking rigidly to those
(advised) conventions.
The conventions which I am recommending in this series have been
discussed with and approved of by Colton Software.
A custom function is a sequence of commands which start with a
-áfunctioná- command and end with a -áresultá- command. Once there is
a custom function within a document then the whole document is a custom
function document. Custom function documents behave differently from
'ordinary' documents (in particular, the sequence in which the slots
are evaluated) - but they do not have a different file type!
Parameters are a 'sort of' variable which can be passed to custom
functions. It is a convention (not a constraint of '4Prol') that they
retain their identity and value throughout the custom function. You
can consider parameters to be variables which don't 'vary' within the
custom function.
The following conventions (not constraints) apply to the use of names
within a custom function. Local variables should be declared as names
rather than using slots for local variables. It is a convention (not a
constraint) to use the -áset_name("name",slotref)á- command once only.
Use it to assign a slot in the workspace to the local variable name.
Thereafter, it is conventional to change the value of the local
variable with the -áset_value(name,value)á- command rather than with
the -áset_name("name",value)á¡ command.
High Technology Information Processing Systems
Some many years ago, when I had to give a series of introductory
lectures on 'Those new computer things' (meaning PCs as opposed to
mainframes) to skilled professionals who were 'non-computerate' (I
hated that phrase), I would start by writing the heading of this
paragraph on the blackboard (or OHP film). Then I would go on to
explain the meanings of the words, emphasising that 'digital
electronics' were used for coding, storing and processing information
and leading a discussion ('student centred learning' was in vogue) of
the advantages and disadvantages of 'electronic' processing. Part way
into the first lecture I would suggest that a useful way of classifying
such 'Systems' was in terms of the way in which the data (information)
was created and processed.
The first category I called "System created" and it consisted
essentially of minimal input and maximum processing by the 'System'.
Because data storage (memory) was limited on early computers they
tended to be of the "System created" type. A good example is a prime
number generator. Another example is a program in which you enter a
year (for which the program is guaranteed to give valid answers) and
the output is the date of Easter Sunday for that year. By the way, I
have been sent an algorithm for Easter by Brian Edwards which is said
to 'work' back to the year 1200. He has implemented the algorithm as a
BASIC program. I have 'converted' it (the algorithm) to a PipeDreamá4
custom function. If you have anything relating to the subject of 'old'
Easters (for publication or just for interest) then please write to me
in time for the Novemberá1992 PipeLineá4 disc.
The second category I called "User created". Examples are simple text
editors and simple 'store and retrieve' databases. Early programs of
this type used the 'IP System' as an 'electronic' storage system with
little if any processing. More recently (since 1980) the processing
element of such 'IP Systems' has increased starting with formatting
(paragraphs etc in WP 'Systems') and Search and Sort routines for
databases and now with more sophisticated label printing and
mail merge routines.
The third category I called "Expert created". Some of the earlier
"Expert created IP Systems" included telephone directories and the
Bible where the 'System' was used mainly as a rapid access store. More
modern expert systems include a medical diagnostic system and I think
that you might include many of the systems which use CD multi media
discs in this category.
Data Validation
Let us not worry too much about classification. What is important is
that whatever data you (or anyone else) enters into such a system must
be data which is within the range for which the 'System' gives valid
answers. This brings me round to 'Data Validation' and 'Conditional
Execution' - essentially you want your custom function to be executed
if and only if it gives the correct answer for the data which has been
entered.
For example, in the UK the way in which leap years are calculated
changed in the year 1752 so, if the custom function you write gives
correct answers only for years after 1752 then you must 'test' whether
the year input is before or after 1752. What I have rather loosely
called a 'good' program would test the data entered and execute the
custom function only if the result is valid.
A rather more sophisticated custom function for determining if a year
is a leap year could 'work' for dates from 5AD onwards (8AD was the
first leap year). Such a custom function would use one formula for
years after 1752 and a different formula for years between 5AD and
1752. If you wished to make the custom function even more
'sophisticated' then you could take into account the fact that some
countries changed their calendar not in 1752 but in some earlier or
later year! For such a custom function to return the 'correct' value
you would have to enter not only the year but also the country.
What I am getting round to is that a most useful command in any
programming language is one which tests a condition and, if the
condition is true one sequence of commands is used, whereas, if the
condition is false another sequence has to be used.
In '4ProL' the command is called -áifá- and the syntax is:
-áif(condition,do_if_true,do_if_false)
The -áconditioná- often involves testing if one variable is equal,
greater than or less than another; it can always be framed as a
question (eg "Has 'Fred' more than 85%PC% in his maths exam?"). If the
answer to the question is "Yes" then the condition is true and the
command I have called -ádo_if_trueá- is executed; if the answer is "No"
then -ádo_if_falseá- is executed.
It's time to look at an example. Double click on the file [StuGrade]
in this directory and you will find that it and a custom function
document called [c_Grading] are loaded. What the first custom function
(called from [StuGrade] column D) does is to award a grade
('Distinction', 'Merit', 'Pass' or 'Fail') according to the mark
(between 0%PC% and 100%PC%) shown in [StuGrade] column B. The mark for
student Fred Bloggs is in [Stugrade]B4 and, with 65%PC% he is awarded a
merit. Try a few more values between 0%PC% and 100%PC% (ignore for now the
comments in the E column) and you will find Fred's grade changes at
40%PC%, 65%PC% and 85%PC%.
Where does the data validation come in? Well, if the student has a
negative mark or one over 100%PC% then it is likely that a typing error
was made during "data entry" into [StuGrade]B4 and you will not want a
grade to be calculated but you will want an "error message" to be
returned instead. Try giving Fred 1000%PC% or -10%PC% and see what is
returned in slot [StuGrade]D4.
Conditional Execution
Now let's have a look at the custom function -á[c_Grading]gradeá- and
see how the input data is validated.
The two lines which are used to validate the input data are
[c_Grading]A15 and [c_Grading]A16. The '4ProL' command used is the
-áifá- command. In [c_Grading]A15 the -áconditioná- can be phrased as
the question "Is the parameter @@marks greater than 100?" (Note that
@@marks needs an @@ sign in front of it since it has been passed as a
parameter to the function and it is not a name - see the tutorials in
Custom01 and Custom02).
If the condition is true (ie if the answer to the question is "Yes")
then you don't want to find the corresponding grade but you want to
return an error message instead. One simple way of implementing this
is to return from the custom function immediately by using the command
-áresult("Over 100?")á- as I have done here.
If the condition is false (the answer to the question is "No") then you
want to find the grade (using [c_Grading]C20 to C25) corresponding to
@@marks. If you look at the command in [c_Grading]C15 you will find
...if(@@marks>100,result("Over 100%PC%"?),)
and I want you to notice that the last two characters are -á,)á- so
there is no -ádo_if_falseá- command. The effect of there being no such
command is that the "Sequence" (see the earlier tutorials) of commands
executed continues down column A of the custom function. In this case
the 'program pointer' moves down to [c_Grading]A16 and tests for a
negative @@marks in a similar way.
Using an Inequality
If @@marks is not greater than 100 and not less than 0 then it must lie
between 0 and 100 inclusive! Lines [c_Grading]A20 to A23 are all of
the same type as those we have just studied but let's have a look at
what happens in detail if @@marks has the value 60.
As recommended in the earlier tutorials, at the beginning of the custom
function, in slot [c_Grading]A10 I have declared the variable name
"grade_awarded" allocating to it slot [c_Grading]B10. After using
-áset_name("name",slotref)á- once (and once only) this way I use the
command -áset_value(name,value)á- in [c_Grading]A20 to A23 to change
its value. Looking first at [c_Grading]A20, if @@marks = 60 then it is
certainly less than 100 so the condition is true (a "Yes"). Hence a
"Distinction" is (provisionally) awarded to our hero Fred. His elation
(if he could read quickly enough) would be short lived because the
'program pointer' moves on to the next slot and, in the same way,
awards Fred a "Merit". Poor Fred, his trauma is not yet over because
the condition in [c_Grading]A22 is also true and so Fred gets a "Pass"!
If you look at the next line, the condition asks the question "Is
@@marks<40?" to which the answer is "No" and Fred's "Pass" is upheld.
He does not get awarded a "Fail" because the command
-áset_value(grade_awarded,"Fail -")á- is not executed.
Only the final value of the name "grade_awarded" is returned from slot
[c_Grading]A25 to slot [StuGrade]D4 so that, whilst [c_Grading]B10 has
changed from its original value to "Distinction", then to "Merit" and
finally to "Pass", the value in [StuGrade]D4 is only 'updated' when the
'program pointer' has passed from [c_Grading]A25 back to [StuGrade]D4.
Using an Equality
Rather than using less than (eg @@marks<100), in the next custom
function I have used equalities. This next custom function is called
from [StuGrade]E4 as -á[c_Grading]first_comment(C4)á- with one
parameter, the value held in slot [StuGrade]C4. Note that the value in
[StuGrade]C4 is text and not a number. I could equally have used
letters such as A, B, C, D, E, etc as codes instead of the characters
0, 1, 2, 3, 4, 5 and 6.
I would like you note how the data is validated. In [c_Grading]A35 I
have assigned a default value to the variable "comment_01". All the
-áif(,,)á- lines of [c_Grading]A37 to A43 are executed because I have
not used -áresult()á- as I did in [c_Grading]A15. However, if the data
is invalid (not one of the characters 0 to 6) then the conditions of
these lines will be false and so -áset_value(comment_01,value)á- will
not be executed. The -áresult(comment_01)á- of [c_Grading]A45 will
then be the default value.
Using a -álookup(,,)á- table
My third custom function -á[c_Grading]second_comment(C4)á- is called
from [StuGrade]E5. It appears in [c_Grading]A48 to A65. Once again,
my strategy for data validation is to set an 'error message' default
value for the variable which is returned by the custom function. If
the @@code is not found in the lookup table then the error message is
returned. Note the 'drop through' value ^# in slot [c_Grading]C74 at
the end of the lookup table. What happens with lookup(,,) is that as
soon as a match is found the rest of the table is discarded. Hence
(for speed) you should put frequent values of @@code at the top of the
table and the 'drop through' value at the end.
I would like you to notice that the columns of the lookup table are
given names in [c_Grading]A51 and A52 and that these names are used in
slot [c_Grading]A57 where there appears:
-áset_value(comment_02,lookup(@@code,code_table,comment_table))
Also, I recommend the convention that the "Expert data" contained in
the lookup table is placed to the right of column B and below the line
containing the -áresult()á- command. The advantage of doing this is
that you can add or delete rows from the custom function with impunity.
If you had data in the same row as a custom function command then
adding new rows would make the data columns 'ragged'. If you delete
such a row then you will lose data.
As an alternative to including 'Expert data' in the custom function, if
it is much larger than the databases of this example, then you should
consider storing the data in a separate dependent document. This
strategy has the advantage that the database can be changed without
changing the custom function file.
Over to you
Generally, unless the "Expert data" is limited to two or three values,
I recommend to you that you use a lookup table as I have done in my
third custom function rather than using the multiple -áifá- commands of
the first two custom functions. Such lookup tables are much more
easily modified than conditions in -áifá- commands. Furthermore, the
lookup table can be searched and sorted.
If the table is a large one then you might use another custom function
to count the usage of each of the @@codes and place the frequencies in a
third column. When you come to 'service' your program you could sort
the lookup table on the frequency column and so speed up future
operations of the function.
What I suggest you do is to rewrite the second custom function so that
it uses a lookup table rather than the multiple -áifá- commands.
When you have done that successfully then try to rewrite the first
function in terms of a table. This is much harder because the first
function uses inequalities; indeed, because of the inequalities you
must use vlookup(,,) instead of lookup(,,). The table must be sorted
in ascending order of @@marks and, if an exact match is not found then
vlookup(,,) will return the grade corresponding to the next lower value
in the @@marks column. If you have insuperable problems then send me a
blank formatted disc, return postage (if possible - difficult if you
live overseas) and a return label; I will provide you with my
vlookup(,,) solution.
Summary
Commands in a custom function can be conditionally executed. A command
used for this is the -áifá- command. One of its principal uses is the
validation of data passed to custom functions as parameters. Indeed,
in larger programs, it is often the case that data validation routines
use more code than the 'wanted' processing!
Lookup tables are preferable to multiple -áifá- statements unless the
number of 'options' are few.
In a later tutorial on 'sub routines' we shall see that -áifá- can be
used to make substantial changes in the sequence in which commands are
executed by calling one sequence if the condition is true and a
completely different sequence if it is false. The usual way of
'Conditional Branching' to a sub routine is to use
-áif(condition,one_routine,alternative_routine)á- as the command.