home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine 1995 / ARCHIVE95.iso / discs / pipeline / abacus / p_line / Custom03 / ReadMe < prev    next >
Text File  |  1992-08-27  |  18KB  |  343 lines

  1. %OP%VS4.13 (28-Apr-92), Gerald L Fitton, R4000 5966 9904 9938 
  2. %OP%DP0
  3. %OP%IRY
  4. %OP%PL0
  5. %OP%HM0
  6. %OP%FM0
  7. %OP%BM0
  8. %OP%LM4
  9. %OP%PT1
  10. %OP%PDPipeLine
  11. %OP%WC1022,2262,168,1748,0,0,0,0
  12. %CO:A,72,72%
  13. %C%Custom Functions from the Beginning - Part 3
  14. %C%by Gerald L Fitton
  15. Keywords:
  16. 4ProL Custom Function Introduction Decision Validation Fitton
  17.  
  18. This is the third tutorial article in the series which I hope will help 
  19. you with PipeDreamá4's custom functions.  The first two articles were 
  20. on an earlier PipeLineá4 disc in the directories Custom01 and Custom02.  
  21. If you wish to write custom functions then you need to learn '4ProL', 
  22. the PipeDreamá4 custom function programming language.
  23.  
  24. If you have a deep screen mode then it is preferable to use it because 
  25. it will make it easier to see substantial parts of the custom function 
  26. without losing the document which 'calls' it.  If not, then you will 
  27. have to use mode 12 and scroll through the documents as is necessary.  
  28. I am using the Atomwide VIDC mode 102 with an Eizo 9070S multiscan and 
  29. an A540 Archimedes.  This monitor-mode combination has a screen depth 
  30. of over 50 lines and a screen width of over 130 system font characters 
  31. when using PipeDream.  Mode 12 is about half that width and depth, a 
  32. quarter of the area!
  33.  
  34. The module DeskModes (in the Mode directory of the 4PL9208 disc) by 
  35. David Holden will give you a wider (up to 96 characters) and deeper (up 
  36. to 36 rows) screen on a standard resolution monitor.  Unless you have 
  37. something better then I suggest that you use one of his modes rather 
  38. than Mode 12.
  39.  
  40. Summary of parts 1 and 2
  41. I am calling Colton Software's PipeDreamá4 Programming Language '4ProL' 
  42. (until someone comes up with a better name - there is a prize for a 
  43. better name).
  44.  
  45. Designing a new language such as '4ProL' is always a compromise. 
  46. The compromise is between:
  47.  
  48. (a) Including commands which provide the flexibility needed to carry 
  49.     out complex or intricate processes quickly and
  50. (b) Inherent constraints which encourage those 'good' programming 
  51.     techniques needed to facilitate debugging and program improvements.
  52.  
  53. The compromise is to learn a set of conventions (a sub set of the 
  54. constraints of the language) which encourage 'good' programming and to 
  55. aim to write 'well written' programs.  Only after becoming master of 
  56. the conventions should you break them knowing that you need speed or 
  57. efficiency which can not be achieved by sticking rigidly to those 
  58. (advised) conventions.
  59.  
  60. The conventions which I am recommending in this series have been 
  61. discussed with and approved of by Colton Software.
  62.  
  63. A custom function is a sequence of commands which start with a 
  64. -áfunctioná- command and end with a -áresultá- command.  Once there is 
  65. a custom function within a document then the whole document is a custom 
  66. function document.  Custom function documents behave differently from 
  67. 'ordinary' documents (in particular, the sequence in which the slots 
  68. are evaluated) - but they do not have a different file type!
  69.  
  70. Parameters are a 'sort of' variable which can be passed to custom 
  71. functions.  It is a convention (not a constraint of '4Prol') that they 
  72. retain their identity and value throughout the custom function.  You 
  73. can consider parameters to be variables which don't 'vary' within the 
  74. custom function.
  75.  
  76. The following conventions (not constraints) apply to the use of names 
  77. within a custom function.  Local variables should be declared as names 
  78. rather than using slots for local variables.  It is a convention (not a 
  79. constraint) to use the -áset_name("name",slotref)á- command once only.  
  80. Use it to assign a slot in the workspace to the local variable name.  
  81. Thereafter, it is conventional to change the value of the local 
  82. variable with the -áset_value(name,value)á- command rather than with 
  83. the -áset_name("name",value)á¡ command.
  84.  
  85. High Technology Information Processing Systems
  86. Some many years ago, when I had to give a series of introductory 
  87. lectures on 'Those new computer things' (meaning PCs as opposed to 
  88. mainframes) to skilled professionals who were 'non-computerate' (I 
  89. hated that phrase), I would start by writing the heading of this 
  90. paragraph on the blackboard (or OHP film).  Then I would go on to 
  91. explain the meanings of the words, emphasising that 'digital 
  92. electronics' were used for coding, storing and processing information 
  93. and leading a discussion ('student centred learning' was in vogue) of 
  94. the advantages and disadvantages of 'electronic' processing.  Part way 
  95. into the first lecture I would suggest that a useful way of classifying 
  96. such 'Systems' was in terms of the way in which the data (information) 
  97. was created and processed.
  98.  
  99. The first category I called "System created" and it consisted 
  100. essentially of minimal input and maximum processing by the 'System'.  
  101. Because data storage (memory) was limited on early computers they 
  102. tended to be of the "System created" type.  A good example is a prime 
  103. number generator.  Another example is a program in which you enter a 
  104. year (for which the program is guaranteed to give valid answers) and 
  105. the output is the date of Easter Sunday for that year.  By the way, I 
  106. have been sent an algorithm for Easter by Brian Edwards which is said 
  107. to 'work' back to the year 1200.  He has implemented the algorithm as a 
  108. BASIC program.  I have 'converted' it (the algorithm) to a PipeDreamá4 
  109. custom function.  If you have anything relating to the subject of 'old' 
  110. Easters (for publication or just for interest) then please write to me 
  111. in time for the Novemberá1992 PipeLineá4 disc.
  112.  
  113. The second category I called "User created".  Examples are simple text 
  114. editors and simple 'store and retrieve' databases.  Early programs of 
  115. this type used the 'IP System' as an 'electronic' storage system with 
  116. little if any processing.  More recently (since 1980) the processing 
  117. element of such 'IP Systems' has increased starting with formatting 
  118. (paragraphs etc in WP 'Systems') and Search and Sort routines for 
  119. databases and now with more sophisticated label printing and
  120. mail merge routines.
  121.  
  122. The third category I called "Expert created".  Some of the earlier 
  123. "Expert created IP Systems" included telephone directories and the 
  124. Bible where the 'System' was used mainly as a rapid access store.  More 
  125. modern expert systems include a medical diagnostic system and I think 
  126. that you might include many of the systems which use CD multi media 
  127. discs in this category.
  128.  
  129. Data Validation
  130. Let us not worry too much about classification.  What is important is 
  131. that whatever data you (or anyone else) enters into such a system must 
  132. be data which is within the range for which the 'System' gives valid 
  133. answers.  This brings me round to 'Data Validation' and 'Conditional 
  134. Execution' - essentially you want your custom function to be executed 
  135. if and only if it gives the correct answer for the data which has been 
  136. entered.
  137.  
  138. For example, in the UK the way in which leap years are calculated 
  139. changed in the year 1752 so, if the custom function you write gives 
  140. correct answers only for years after 1752 then you must 'test' whether 
  141. the year input is before or after 1752.  What I have rather loosely 
  142. called a 'good' program would test the data entered and execute the 
  143. custom function only if the result is valid.
  144.  
  145. A rather more sophisticated custom function for determining if a year 
  146. is a leap year could 'work' for dates from 5AD onwards (8AD was the 
  147. first leap year).  Such a custom function would use one formula for 
  148. years after 1752 and a different formula for years between 5AD and 
  149. 1752.  If you wished to make the custom function even more 
  150. 'sophisticated' then you could take into account the fact that some 
  151. countries changed their calendar not in 1752 but in some earlier or 
  152. later year!  For such a custom function to return the 'correct' value 
  153. you would have to enter not only the year but also the country.
  154.  
  155. What I am getting round to is that a most useful command in any 
  156. programming language is one which tests a condition and, if the 
  157. condition is true one sequence of commands is used, whereas, if the 
  158. condition is false another sequence has to be used.
  159.  
  160. In '4ProL' the command is called -áifá- and the syntax is:
  161.  
  162. -áif(condition,do_if_true,do_if_false)
  163.  
  164. The -áconditioná- often involves testing if one variable is equal, 
  165. greater than or less than another; it can always be framed as a 
  166. question (eg "Has 'Fred' more than 85%PC% in his maths exam?").  If the 
  167. answer to the question is "Yes" then the condition is true and the 
  168. command I have called -ádo_if_trueá- is executed; if the answer is "No" 
  169. then -ádo_if_falseá- is executed.
  170.  
  171. It's time to look at an example.  Double click on the file [StuGrade] 
  172. in this directory and you will find that it and a custom function 
  173. document called [c_Grading] are loaded.  What the first custom function 
  174. (called from [StuGrade] column D) does is to award a grade 
  175. ('Distinction', 'Merit', 'Pass' or 'Fail') according to the mark 
  176. (between 0%PC% and 100%PC%) shown in [StuGrade] column B.  The mark for 
  177. student Fred Bloggs is in [Stugrade]B4 and, with 65%PC% he is awarded a 
  178. merit.  Try a few more values between 0%PC% and 100%PC% (ignore for now the 
  179. comments in the E column) and you will find Fred's grade changes at 
  180. 40%PC%, 65%PC% and 85%PC%.
  181.  
  182. Where does the data validation come in?  Well, if the student has a 
  183. negative mark or one over 100%PC% then it is likely that a typing error 
  184. was made during "data entry" into [StuGrade]B4 and you will not want a 
  185. grade to be calculated but you will want an "error message" to be 
  186. returned instead.  Try giving Fred 1000%PC% or -10%PC% and see what is 
  187. returned in slot [StuGrade]D4.
  188.  
  189. Conditional Execution
  190. Now let's have a look at the custom function -á[c_Grading]gradeá- and 
  191. see how the input data is validated.
  192.  
  193. The two lines which are used to validate the input data are 
  194. [c_Grading]A15 and [c_Grading]A16.  The '4ProL' command used is the 
  195. -áifá- command.  In [c_Grading]A15 the -áconditioná- can be phrased as 
  196. the question "Is the parameter @@marks greater than 100?" (Note that 
  197. @@marks needs an @@ sign in front of it since it has been passed as a 
  198. parameter to the function and it is not a name - see the tutorials in 
  199. Custom01 and Custom02).
  200.  
  201. If the condition is true (ie if the answer to the question is "Yes") 
  202. then you don't want to find the corresponding grade but you want to 
  203. return an error message instead.  One simple way of implementing this 
  204. is to return from the custom function immediately by using the command 
  205. -áresult("Over 100?")á- as I have done here.
  206.  
  207. If the condition is false (the answer to the question is "No") then you 
  208. want to find the grade (using [c_Grading]C20 to C25) corresponding to 
  209. @@marks.  If you look at the command in [c_Grading]C15 you will find
  210.  
  211. ...if(@@marks>100,result("Over 100%PC%"?),)
  212.  
  213. and I want you to notice that the last two characters are -á,)á- so 
  214. there is no -ádo_if_falseá- command.  The effect of there being no such 
  215. command is that the "Sequence" (see the earlier tutorials) of commands 
  216. executed continues down column A of the custom function.  In this case 
  217. the 'program pointer' moves down to [c_Grading]A16 and tests for a 
  218. negative @@marks in a similar way.
  219.  
  220. Using an Inequality
  221. If @@marks is not greater than 100 and not less than 0 then it must lie 
  222. between 0 and 100 inclusive!  Lines [c_Grading]A20 to A23 are all of 
  223. the same type as those we have just studied but let's have a look at 
  224. what happens in detail if @@marks has the value 60.
  225.  
  226. As recommended in the earlier tutorials, at the beginning of the custom 
  227. function, in slot [c_Grading]A10 I have declared the variable name 
  228. "grade_awarded" allocating to it slot [c_Grading]B10.  After using 
  229. -áset_name("name",slotref)á- once (and once only) this way I use the 
  230. command -áset_value(name,value)á- in [c_Grading]A20 to A23 to change 
  231. its value.  Looking first at [c_Grading]A20, if @@marks = 60 then it is 
  232. certainly less than 100 so the condition is true (a "Yes").  Hence a 
  233. "Distinction" is (provisionally) awarded to our hero Fred.  His elation 
  234. (if he could read quickly enough) would be short lived because the 
  235. 'program pointer' moves on to the next slot and, in the same way, 
  236. awards Fred a "Merit".  Poor Fred, his trauma is not yet over because 
  237. the condition in [c_Grading]A22 is also true and so Fred gets a "Pass"!  
  238. If you look at the next line, the condition asks the question "Is 
  239. @@marks<40?" to which the answer is "No" and Fred's "Pass" is upheld.  
  240. He does not get awarded a "Fail" because the command 
  241. -áset_value(grade_awarded,"Fail -")á- is not executed.
  242.  
  243. Only the final value of the name "grade_awarded" is returned from slot 
  244. [c_Grading]A25 to slot [StuGrade]D4 so that, whilst [c_Grading]B10 has 
  245. changed from its original value to "Distinction", then to "Merit" and 
  246. finally to "Pass", the value in [StuGrade]D4 is only 'updated' when the 
  247. 'program pointer' has passed from [c_Grading]A25 back to [StuGrade]D4.
  248.  
  249. Using an Equality
  250. Rather than using less than (eg @@marks<100), in the next custom 
  251. function I have used equalities.  This next custom function is called 
  252. from [StuGrade]E4 as -á[c_Grading]first_comment(C4)á- with one 
  253. parameter, the value held in slot [StuGrade]C4.  Note that the value in 
  254. [StuGrade]C4 is text and not a number.  I could equally have used 
  255. letters such as A, B, C, D, E, etc as codes instead of the characters 
  256. 0, 1, 2, 3, 4, 5 and 6.
  257.  
  258. I would like you note how the data is validated.  In [c_Grading]A35 I 
  259. have assigned a default value to the variable "comment_01".  All the 
  260. -áif(,,)á- lines of [c_Grading]A37 to A43 are executed because I have 
  261. not used -áresult()á- as I did in [c_Grading]A15.  However, if the data 
  262. is invalid (not one of the characters 0 to 6) then the conditions of 
  263. these lines will be false and so -áset_value(comment_01,value)á- will 
  264. not be executed.  The -áresult(comment_01)á- of [c_Grading]A45 will 
  265. then be the default value.
  266.  
  267. Using a -álookup(,,)á- table
  268. My third custom function -á[c_Grading]second_comment(C4)á- is called 
  269. from [StuGrade]E5.  It appears in [c_Grading]A48 to A65.  Once again, 
  270. my strategy for data validation is to set an 'error message' default 
  271. value for the variable which is returned by the custom function.  If 
  272. the @@code is not found in the lookup table then the error message is 
  273. returned.  Note the 'drop through' value ^# in slot [c_Grading]C74 at 
  274. the end of the lookup table.  What happens with lookup(,,) is that as 
  275. soon as a match is found the rest of the table is discarded.  Hence 
  276. (for speed) you should put frequent values of @@code at the top of the 
  277. table and the 'drop through' value at the end.
  278.  
  279. I would like you to notice that the columns of the lookup table are 
  280. given names in [c_Grading]A51 and A52 and that these names are used in 
  281. slot [c_Grading]A57 where there appears:
  282.  
  283. -áset_value(comment_02,lookup(@@code,code_table,comment_table))
  284.  
  285. Also, I recommend the convention that the "Expert data" contained in 
  286. the lookup table is placed to the right of column B and below the line 
  287. containing the -áresult()á- command.  The advantage of doing this is 
  288. that you can add or delete rows from the custom function with impunity.  
  289. If you had data in the same row as a custom function command then 
  290. adding new rows would make the data columns 'ragged'.  If you delete 
  291. such a row then you will lose data.
  292.  
  293. As an alternative to including 'Expert data' in the custom function, if 
  294. it is much larger than the databases of this example, then you should 
  295. consider storing the data in a separate dependent document.  This 
  296. strategy has the advantage that the database can be changed without 
  297. changing the custom function file.
  298.  
  299. Over to you
  300. Generally, unless the "Expert data" is limited to two or three values, 
  301. I recommend to you that you use a lookup table as I have done in my 
  302. third custom function rather than using the multiple -áifá- commands of 
  303. the first two custom functions.  Such lookup tables are much more 
  304. easily modified than conditions in -áifá- commands.  Furthermore, the 
  305. lookup table can be searched and sorted.
  306.  
  307. If the table is a large one then you might use another custom function 
  308. to count the usage of each of the @@codes and place the frequencies in a 
  309. third column.  When you come to 'service' your program you could sort 
  310. the lookup table on the frequency column and so speed up future 
  311. operations of the function.
  312.  
  313. What I suggest you do is to rewrite the second custom function so that 
  314. it uses a lookup table rather than the multiple -áifá- commands.
  315.  
  316. When you have done that successfully then try to rewrite the first 
  317. function in terms of a table.  This is much harder because the first 
  318. function uses inequalities; indeed, because of the inequalities you 
  319. must use vlookup(,,) instead of lookup(,,).  The table must be sorted 
  320. in ascending order of @@marks and, if an exact match is not found then 
  321. vlookup(,,) will return the grade corresponding to the next lower value 
  322. in the @@marks column.  If you have insuperable problems then send me a 
  323. blank formatted disc, return postage (if possible - difficult if you 
  324. live overseas) and a return label; I will provide you with my 
  325. vlookup(,,) solution.
  326.  
  327. Summary
  328. Commands in a custom function can be conditionally executed.  A command 
  329. used for this is the -áifá- command.  One of its principal uses is the 
  330. validation of data passed to custom functions as parameters.  Indeed, 
  331. in larger programs, it is often the case that data validation routines 
  332. use more code than the 'wanted' processing!
  333.  
  334. Lookup tables are preferable to multiple -áifá- statements unless the 
  335. number of 'options' are few.
  336.  
  337. In a later tutorial on 'sub routines' we shall see that -áifá- can be 
  338. used to make substantial changes in the sequence in which commands are 
  339. executed by calling one sequence if the condition is true and a 
  340. completely different sequence if it is false.  The usual way of 
  341. 'Conditional Branching' to a sub routine is to use 
  342. -áif(condition,one_routine,alternative_routine)á- as the command.
  343.