Practical Uses of a Model of APL Abstract This paper discusses the use of a general model of APL
(written in APL) which allows convenient definition of new
operators and functions and experimentation with their use.
Use of the model is illustrated by a number of functions and
operators, some of which have been previously discussed,
and some (such as the operator til) which are new.
Details of the model itself are not treated.
Introduction The effective use of new facilities introduced into APL systems is often long delayed, not only because of a programmer’s tendency to cling to familiar ways, but also because the abstract, formal treatment necessary to the specification of a new facility often makes its assimilation and use seem unduly difficult. Working models of new facilities available before their actual introduction can be very helpful in teaching, their use, and very effective in speeding their widespread application. However, the development of an accurate model for each new facility can, especially in the case of new operators, be burdensome, and we have found that a general model of the APL interpreter, developed primarily for use by the language designers in the design and modelling of new extensions, can also be useful in providing specific models for the enlightenment of users. This paper discusses such uses of the general model, employing illustrations executed by the version available on the I.P. Sharp Associates APL system. Except for information necessary for understanding its use, details of the model will not be discussed here. The model incorporates a number of facilities proposed in earlier papers [1 2 3]; the more fundamental among them are illustrated below. The model, invoked by executing the function ∆APL , accepts character input and parses and executes the expression entered. 0-origin indexing is used throughout the paper.
Assignment of values to graphic symbols is, of course, intended for use in language design, and is not proposed for general inclusion in the language. It is, nevertheless, convenient for use in experimentation by programmers as well as by language designers. The use of new composite symbols is possible because the model receives and handles arbitrary input (⎕arbin in IPSA APL), that is, all terminal inputs including backspace and attention are transmitted directly to it. The model also incorporates a definition from [1] which illustrates the notion that an operator may produce an ambivalent derived function — specifically, the monadic derived function produced by reduction is supplemented by a dyadic case in which the left argument specifies the width of the “window” over which reduction is applied. For example:
A. Some New Functions We will further illustrate the use of the model in simple cases by defining a few functions (most of which have been defined in earlier papers [1 2]) for use in later examples:
B. Enclosed Arrays Enclosed arrays provide a good example of a notion whose formal treatment makes it seem unduly difficult. For example, a graphic display of enclosed arrays is very helpful to the beginner, but the definition of a suitable display is recursive and somewhat complicated. However, its behaviour is immediately evident from a model. The definition of display, (i.e., of the function ⍕) used here, is a modification (due largely to P.K. Wooster) of the definition in [2], and may be illustrated as follows: ⎕ps←0 0 ¯3 ¯3 ⎕←q←2 2⍴(<a),(<(<c1),<c2),<a∘.×a |¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯| ||¯¯| |¯¯|| |1 2 3| ||ba| |be|| |_____| ||re| |ar|| ||__| |__|| |_________| |¯¯¯¯¯| |1 2 3| |¯¯¯¯¯| |2 4 6| |1 2 3| |3 6 9| |_____| |_____| The last two elements of the system variable ⎕ps determine the row and column spacing between enclosed elements, injecting “box” decorations in one of the spaces if the arguments are negative. The first two elements control the vertical and horizontal positioning of the elements, ¯1 denoting top (or left) justification, 0 centering, and 1 bottom (or right) justification. For example: ⎕ps←¯1 1 0 3 q 1 2 3 ba be re ar 1 2 3 1 2 3 2 4 6 3 6 9 In later examples it will be convenient to use two further functions. The first is the boolean match (called idem in [3]), denoted by ≡ , which compares its left and right arguments and yields a scalar 0 unless they match in every respect. We will also define its monadic case to yield 1 if its argument is simple, that is, contains no enclosed elements. The second function is a variant of link, defined as follows: ;←'(<⍺),∆⍵' ∇ '⍵ ⋄ <⍵ ⋄ →≡⍵' In words, ;x encloses x if x is simple, and x;y catenates the enclose of x to y , first enclosing y if it is simple. For example: ⎕ps←0 0 ¯3 ¯3 c1;c2 |¯¯| |¯¯| |ba| |be| |re| |ar| |__| |__| c1;c2;a |¯¯| |¯¯| |¯¯¯¯¯| |ba| |be| |1 2 3| |re| |ar| |_____| |__| |__| ;⌿c1 |¯¯| |¯¯| |ba| |re| |__| |__| q≡2 2⍴a;(c1;c2);a∘.×a 1 The ∆ occurring in the definition
of ; is a “self-reference”
to the function being defined
[3];
since it is used monadically,
it refers to the monadic case
and therefore encloses its argument
if it is simple.
It should also be noted
that this use of the semicolon
as a function need not conflict
with its use as a
separator in bracket indexing.
C. The Disposition of Axes The effect of an axis operator in an expression such as f⍤1 0 t is simply to apply the function f to the subarrays along the indicated axes of the argument t , and the axes resulting from applying f to each subarray are placed last in the overall result. As simple as these rules are, their effects can be bewildering until the user develops some familiarity with their application in specific instances. Such familiarity can be gained by applying some simple function (such as ravel or scan) in a number of eases:
Although the definition of the axis operator used here is adopted from [2], the representation of the right argument i differs slightly; the older definition would be satisfied by replacing f⍤i by f⍤(;i) . In other words, an enclosed right argument is treated as in [2], but a simple argument is treated as a single entity and specifies (in the dyadic case of the resulting function) both the left and right axes of application. For example: c1 ba re c2 be ar c1,⍤1 c2 babe bear c1,⍤0 c2 brba aeer D. Composition and Related Operators For a single scalar argument s , the composition of two functions f and g (denoted by f⍤g) is easy to understand, since f⍤g s is equivalent to f g s . For example: ⍳⍤⌊ 3.6 ⍳⌊3.6 0 1 2 0 1 2 +/⍤⍳⍤⌊ 3.6 +/⍳⌊ 3.6 3 3 However, much of the importance (and difficulty) of composition stems from its use with non-scalar arguments, in which case the entire composed function f⍤g is applied individually to each of the subarrays to which g (according to its axes of application) applies. For example: +/⍤⍳⍤⌊ v← 2.5 3.6 4.9 6.4 1 3 6 15 ⎕←l← <⍤⍳⍤⌊ v |¯¯¯| |¯¯¯¯¯| |¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯| |0 1| |0 1 2| |0 1 2 3| |0 1 2 3 4 5| |___| |_____| |_______| |___________| +/⍤> l 1 3 6 15 Note that the expressions +/⍳⌊ and <⍳⌊ and +/> corresponding to the foregoing compositions would not even be valid for the given arguments. In some cases, the corresponding expressions are valid, but yield different results. For example: a←3 2 2⍴1 0 1 1 1 0 2 1 1 0 3 1 a ⌹a ⍉⍤⌹a ⍉⌹a 1 0 1 0 1 ¯1 1 1 1 1 1 ¯1 1 0 1 ¯1 ¯2 ¯3 1 0 1 0 1 ¯2 0 0 0 2 1 ¯2 1 0 1 1 1 1 1 0 1 0 1 ¯3 3 1 ¯3 1 0 1 The operator denoted by ¨ (called with in [2]) applies in two distinct ways. Applied to a function and a variable, it produces the monadic function obtained by supplying the variable as one argument of the (dyadic) function. For example: (exp←10¨*) 1 2 3 10 100 1000 (sq←*¨2) 1 2 3 149 Applied to two functions, as in f¨g , it is equivalent to composition, with a final application of the function gi which is inverse to g . Thus, for a scalar argument s , we have f¨g s ←→ gi f g s . The extension to general arguments is like that of composition. For example:
In the foregoing discussion of the operators ¨ and ⍤ , only the monadic case of the derived function was considered, that is, it was applied to a single argument. The dyadic cases of f⍤g and f¨g are similar, the function g being applied (along appropriate axes) to both the left and right arguments. For example: a +⍤÷ b←1+a←1 2 3 1.5 0.83333333 0.58333333 a+¨÷b 0.66666667 1.2 1.71428571 c ×⍤(+/⍤0) c←3 3⍴⍳9 81 144 225 The composition in the expression a f⍤g b (referred to in [2] as f on g) applies the dyadic (case of the) function f to the results of the monadic function g ; the composition in the expression a f⍥g b (to be referred to as f upon g) applies the monadic function f to the result of dyadic g , as in f a g b . The difference may be illustrated as follows: c1 c2 ba be re ar c1 ,⍤, c2 barebear c1 ,⍥, c2 baberear a <⍤÷ b←⌽a←1 2 3 4 0 0 1 1 a <⍥÷ b |¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯| |¯¯¯| |¯| |0.25| |0.66666667| |1.5| |4| |____| |__________| |___| |_| We will conclude this section with a rather complex expression involving operators, the purpose being to illustrate how to “read” such expressions. If: a←2 3 4 5⍴⍳120 v←(i←1);(j←2 0);(k←3);(l←4 2 0) then it is possible to write a function of v such that the ravel of a indexed by its result is equivalent to a[i;j;k;l] . Thus: a[i;j;k;l] ≡ (,a)[>∘.+¨>/vר>r⊥ An understanding of the expression in the brackets can be gained by executing it piece-by-piece: ⎕←z←r⊥ The expression for z
(whose details were shown in Section A)
yields the weights appropriate to the successive axes
in indexing the ravel of the argument a .
The vector y is obtained
by multiplying each element
of the list of indices (v)
by the appropriate weight,
and the final result shown is the application
of the plus-outer-product (∘.+)
between each of the disclosed elements
of y .
E. The Definition of Operators A dyadic operator can be defined in terms of expressions
involving its two arguments
(to be denoted by ⍺
and ⍵ and the
two arguments of the derived function produced (to be denoted
by ⍺ and ⍵).
For example, if the dyadic
operator Since either or both of the arguments ⍺ or ⍵ may be either a variable or a function, and since definitions must sometimes be provided for two or more of the four possible cases, each definition will be associated with an indication of the case it defines. For example, if
then ⌊ In general, the definition of a dyadic operator requires as the left argument of ∇ a vector whose kth element is the enclosed representation (using 0 to denote a variable and 1 to denote a function) of the case represented by the kth element of the right argument. In the definition of a monadic operator, each case is indicated by a single quantity, and the left argument of ∇ is therefore one of 0 , or 1 , or 0;1 , or 1;0 . We will conclude this section with the definition of a new dyadic operator denoted by ⍨ (and called til as an abbreviation of tilde): ⍨←1 1 ∇ '''(⍵⍵)⍺⍺''∇''⍵∆⍵''' This operator is of great practical interest because it subsumes a number of important special cases arising from its use with the identity function ⊢ (defined as ⊢←'⍵'∇'⍵'), and with a sequence of functions, as in f⍨g⍨h :
F. Merge as a Dyadic Case of Selection If s is a dyadic selection function such that i s a selects from a an array determined by the “indices” (or other parameters) provided by the variable i , then the derived function i¨s is a derived selection function which is monadic, and selection from a is obtained by the expression i¨s a . For example, if m←3 3⍴⍳9 , then 0 0¨⍉ is a monadic selection function such that 0 0¨⍉ selects the diagonal vector 0 4 8 when applied to m . Consider a definition of the dyadic case of such a derived function which returns the entire right argument, but with the elements of the left argument substituted for the selected elements of the right argument. The dyadic function therefore provides a merge of its arguments. For example: m←3 3⍴⍳9 m (10+⍳3) 0 0 ¨⍉ m 0 1 2 10 1 2 3 4 5 3 11 5 6 7 8 6 7 12 This definition of a dyadic case will be extended to other selection functions in the same manner. Consider, for example, the following indexing function, defined in terms of the function q defined at the end of the preceding section: s←'(,⍵)[⍵q⍺]'∇'' ⎕←i←?4 2⍴3 i s m 1 2 5 6 0 3 2 0 0 0 1 0 The function ⌷ (called from) is incorporated in the model using the definition of s above, but adopting the merge definition for the dyadic case of the derived function i¨⌷ . Thus: (10+⍳4) i¨⌷ m 12 1 2 13 4 10 11 7 8 A different approach to the treatment
of merge functions may be found in
[4].
G. Function Attributes An APL function is defined not only by the result it produces for each argument in its domain, but by certain attributes, some of which (like the axes of application) are manifest in every use of the function, and some of which (like the identity element and the inverse) become manifest only upon the application of some operator. For example, the results of the functions ^ and ⌊ are identical for boolean arguments, but differ in their identity elements, ^/⍳0 yielding 1 , and ⌊/⍳0 yielding infinity; the inverse of a function is manifested in the application of the dual operator. The representation of attributes will be introduced into the representation of functions as follows: any segment (as delimited by diamonds) which begins with a right parenthesis represents an attribute; the first token following the parenthesis denotes the name of the attribute specified, and what follows (after the delimiting space) specifies the attribute. For example, the name ∆⌿
denotes the identity element attribute, and the
expression mp←'⍺+.×⍵ ⋄)∆⌿ The following is a list of attributes (together with suggested names) which we have found useful and have incorporated into the APL model:
References
First appeared in APL82, APL Quote-Quad, Volume 13, Number 1, 1982-09.
|