APL/Z by S. Gownowicz Programming Introduction for CP/M by Kevin Smathers Document: APL/Z.1 Initial release: 8/87 Update history: A short introduction This document is tailored for the typical CP/M programmer, who has never used APL before. It is written to complement S. Gownowicz's public domain programming language, APL/Z. The APL programming language was originally defined in a book by Kenneth Iverson, _A_Programming_Language_, published in 1962. Iverson's intention was to create a symbolic language which would be adequate for describing concisely, many important algorithms in mathematics. As a result, the original APL used a myriad of special symbols including subscripts, superscripts and two-dimensional program format with arrows to show flow of control. A modified version of the original APL, termed APL/360 was implemented in the late 60's by Iverson and a group at IBM. Since then APL has been implemented on a variety of machines, all based largely on the APL/360 design. APL has two distinguishing characteristics which set it apart from other languages. 1. It is designed to be interpreted. As such it enjoys all of the unique capabilities that interactive programming languages have. APL includes a number of special features designed exclusively for an interactive environment, inluding immediate execution of expressions entered at the terminal, and entering and editing facilities for subprograms that are associated with a workspace. Workspaces in APL/Z can be saved and restored in part or in whole. 2. APL directly processes entire data structures. In APL the primitive operations accept entire arrays as arguments, and produce arrays as results. Thus in APL the basic unit of data tends to be an array rather than a single array element as in other languages. This emphasis on array-processing gives APL programs a unique appearance quite different from other languages. The specialized character set of APL lends it enough power that a typical one line program can result in a surprising amount of computation. APL is ideally suited for the user who wishes to avoid key-board heavy languages. It is well suited to the interactive environment, because only a few lines of input are required to get the results you might typically be looking for. On the other hand, APL is poorly suited for long programs, or programs which are meant to be maintained over a long period of time. ----- Programming languages specialist Daniel McCracken [1970] notes that it once took him four hours to decode a four- line APL program. Introduction to the APL:ASCII keyboard APL (A Programming Language) is an unstructured language, with a specialized character set devoted to performing the functions of the programming language. In APL there are no lowercase alphabetic symbols. Unshifted letters produce their uppercase counterparts, while shifted letters produce the special APL symbols. To avoid confusion, we will use lowercase symbols for unshifted APL characters. Since CP/M machines typically don't have APL character sets, we will be using some special conventions. They fall into four categories. 1. characters which must be remapped 2. characters which are common to both APL and ASCII 3. characters which cannot be remapped 4. extra characters 1. The characters listed below have been remapped for ascii: _________________________________________________________________ APL ASCII _____________ .. Dieresis (Umlaut) is unmapped (unused in APL) _____________ __ _ High-minus becomes underline _____________ <= { Less-than-or-equal becomes open-brace _____________ >= } Greater-than-or-equal becomes close-brace _____________ /= # Not-equal becomes pound-sign _____________ \/ ! Logical-or becomes exclamation-point _____________ /\ & Logical-and becomes ampersand _____________ x * Times becomes asterisk _____________ . - % Divided-by becomes percent-sign __.__________ <- ` Left-arrow becomes grave-accent _____________ -> @ Right-arrow becomes at-sign __________________________________________________________________ 2. Certain keys on the APL keyboard also appear on the ascii keyboard. These are not remapped. They are: __________________________________________________________________ [ Open bracket ] close bracket ( open paren ) close paren / stroke \ back-stroke , comma . period ; semi-colon : colon + plus - minus < less-than > greater-than = Equals __________________________________________________________________ 3. Apl also uses additional symbols which we won't be mapping. These correspond to the shifted keyboard keys. __________________________________________________________________ Q Question mark see (?) in pt. 4 W Omega the greek symbol E Element epsilon R Rho the greek symbol T Invert (tilde`) see (~) in pt. 4 Y Up-arrow U Down-arrow I iota the greek symbol O circle a large open circle P power see (^) in pt. 4 A alpha the greek symbol S cieling an upside-down 'L' D floor a right-side-up 'L' F underline G del an upside-down delta H delta the greek symbol J little-circle a small open circle K single quote see (') in pt. 4 L quad a large open square Z subset an open semi-circle X superset a close semi-circle C intersection an upside-down 'U' V union a right-side-up 'U' B encode an upside-down 'T' N decode a right-side-up 'T' M vertical bar see (|) in pt. 4 __________________________________________________________________ 4. That leaves us with several ASCII symbols which haven't yet been used, so in order to simplify reading and typing in programs, the rest of the ascii set has been assigned to the characters on the shifed alpha APL keyboard which they most resemble, or whose function they most closely match. __________________________________________________________________ | M ~ T $ H ^ P ' K " K ? Q __________________________________________________________________ Delving into the APL interpreter APL lines begin tabbed in 8 spaces. Here you will type you command, and the interpreter will respond on the next line. 2 2 2+2 4 Here are four dyadic (meaning with two operands) operators you should recognize. 2*3 multiply 6 4%2 divide 2 51 subract 4 2+1 add 3 An important feature to remember about APL is that dyadic operators always use whatever they find immediately on their left side, and the result of evaluating everything on their right. This means that '+' has no precedence over '*'. .___________________. . . . 2*3+16%3 . . + . . + . . + . . + . .___________________. So that this equation would produce: 2*3+16%3 4 This holds true for all operators, not just mathematical ones. However, this sequence can be altered in APL when neccessary, by grouping the term which are to be evaluated first within parentheses. (2*3)+1(6%3) 5 Produces the expected result. These operators can also be applied to lists. A list is simply a sequence of numbers separated by spaces. Try typing 1+1 2 3 2 3 4 2*3 2 1 6 4 2 APL also makes reals available to you, simply by putting a decimal point within the number. Exponential notation can also be used as you would expect. 3.14159*2 6.28318 6.22e12%1000 6.022e9 Remember that uppercase letters are reserved for APL functions. Another operator you will need to know is the unary minus. _3+5 2 And the single quote which is used to create arrays of ASCII data. 'abcde' abcde abcde is a 5 element list. Dyadic operators can also be used on two arrays. In this case, their shapes must be equal. (More on shapes later.) 1 2 3*4 5 6 4 8 10 Operands are paired two at a time, to produce the result. Since arrays are used so frequently in APL, a simple method is provided for creating arrays which count up. In general, the monadic iota function will produce an array starting at 1 and counting up to the argument on it's right side. Iota expects to find a scalar, or a vector of at most one element on it's right side. Monadic Iota: I5 1 2 3 4 5 I5 5 rank error I5 5 ^ Attempting to feed iota a higher degree vector will result in the error shown. APL is complaining that the right hand value is not of the proper rank, also known as dimension. Another dyadic function is the assignment function, left arrow. We will use the grave-accent (`) to represent this character. Values, such as arrays, character arrays, and scalars can be freely assigned to variables using the left-arrow. Variables must be alphabetic, or may additionally start with the symbol delta ($). $hello`'Hi there' hello Hi there 'hello' is an example of a character vector (its shape has one dimension, arrays have more than one dimension in the general case). Remember, variables cannot be uppercase, as those are reserved for the APL functions. The assignment statement introduced above, is another example of a dyadic function. This particular function, however, must use a variable as it's left side. In all other respects, it fits the normal perception of what a dydadic function should be. For example, you might type a line like this: a`1+b`3 Evaluated right to left, this resolves to ( b`3 ),( a`b+1 ). In other words, a will have the value 4 and b will have the value 3. But now that we have these fine variables defined, we will need a way to save and recall them for later use. For this purpose, there are the so called system commands. Basically, system commands are used to make enquiries about the status of the environment or work_space. Here are a few to start with: )VARS list all defined variables )ERASE var_list deallocate a list of variables )SAVE ws_name save the current workspace as ws_name )LOAD ws_name load a workspace from ws_name )FNS list all defined functions Additionally, it should now be high time to go over some of the errors that you may encounter within APL CHARACTER ERROR an unknown character has appeared out of place. SYNTAX ERROR a badly formed expression was typed DOMAIN ERROR the function is not defined for the value given. LENGTH ERROR a binary function was used with unmatched vector shapes VALUE ERROR the indicated variable has not been assigned a value RANK ERROR the number of dimensions of the input is not allowed WS FULL the last function used up all of the unused workspace DEFN ERROR your definition was illegal, one of the variable names was probably at fault. In APL, the standard way of editing is to backspace until you are over the character in error, press ATTN and type the tail of the string again. Otherwize, backspace will not remove characters from the line. Back to functions now, here is another diadic function. The function catenation is represented by a comma (,). For example, a`'hi' b`' there' a,b hi there This is an example of the catenation of two character vectors. Refreshing your memory, a dyadic function is one which acts on two values. A monadic function works with just one value. A niladic function is one which requires no values for input at all. This all leads to user defined functions. The great power of APL is most closely linked with its ability to define functions on the fly which can be used in the same way that all of the system defined functions are. As with all identifiers, function names must begin with an alphabetic (unshifted) letter or delta ($), and may continue with any other alpha or numeric characters, but not APL character set characters. S$ and T$ are reserved variables which will be discussed later. A function is defined as follows: G function_name equations G The surrounding del's (G) are the function definition characters. They open and close the function editor. The function above would have no explicit results, and no input variables. The function would be niladic. A common use for niladic functions without explicit results is to list all of the member functions of a workspace. A niladic function would be written which included that documentation in print statements, and would have a name you could remember such as 'menu'. G menu 'This is a file of useless functions:' 'GRIK: experimental nothing function' 'GRAK: same as above' 'YICK: pretty boring huh?' G menu This is a file of useless functions: GRIK: experimental nothing function GRAK: same as above YICK: pretty boring huh? Non-explicit functions always return each of the results generated on a separate line, as though they had been typed at the keyboard in that sequence. Non-explicit functions do not pass values to other functions. That is the job of the explicit function. G z`pi z`3.1415 G pi 3.1415 2*pi 6.2830 Before exiting the function, the explicit variable in the explicit function declaration must be given a value to return to the next function. The next form of the function declaration is the monadic function. For instance, the following function would change temperatures from Fahrenheit to Celsius. G c ` temp f c ` (f-32) * 5 / 9 G temp 32 0 The full fledged form of the function is a dyadic, explicit function. Listed below are all of the possible combinations which can be used to create a function Argl Explicit Non Explicit 0 Niladic G z`fn G fn 1 Monadic G z`fn a G fn a 2 Dyadic G z`a fn b G a fn b I'd like to take just a moment to digress. When talking about functions in any language, it is important to talk about scoping rules. In basic, where there are no local variables, scoping is global. In Pascal, where a variable name refers to the name most closely linked to its own structural shell, scoping is termed static. In general scoping means, "If I define two variables, both with the name 'x' which one will I be referring to in this procedure?" APL uses a concept of scoping which it has in common with LISP. If the variable is not defined locally, it is checked for locality to the procedure which called it, and if not there, the process is repeated until the variable is found by unwinding the calling stack. This type of scoping is named 'dynamic'. As you must assume from the preceding discussion, APL has its own way of declaring internal variables. These variables are available to all functions called by the function which defined them, until the name is redefined. The form for the declaration of a local variable is as follows: G fn ; lv1 ; lv2 ; lv 3 There may be as many local variables as necessary, each appended to the list with a new semicolon. Old values for the variables named are restored when the function finally returns. The local values are not retained.