APL Syntax and Semantics

Kenneth E. Iverson

I.P. Sharp Associates
Box 418, Exchange Tower
2 First Canadian Place
Toronto, Canada
M5X 1E3



This paper presents a working model of APL syntax and semantics that incorporates explicit representations of functions, operators, and syntax, thus providing a basis for the clear and explicit statement of extended facilities in the language, as well as a tool for experimentation upon them. Use of the model is illustrated in the treatment of the syntax of operators, and in the discussion of a number of new or recently-proposed facilities including indirect assignment, the operators axis, derivative, inverse, and til, and the functions link, and from. The entire model is included in an appendix.

The model is expressed in SHARP APL as extended in [1] but, because it uses few special features (enclose, disclose, close composition, and dual) it should translate easily into other systems (such as NARS [2] and APL2 [3]) that provide some form of enclosed arrays.

We will begin with the overall behaviour of the model as seen in the definition and use of the two outer functions APL and S (the “stack manager” that applies to the left stack L of the expression to be evaluated, and a right stack R of intermediate results), and continue with the tabular definition of syntax, and the representations of functions and operators. 0-origin indexing is used throughout, and enclosed arrays are normally displayed within enclosing vertical bars, as determined by the setting ⎕ps← ¯1 ¯1 0 ¯3 (see Reference [4]).

The function APL accepts literal input and executes the expression entered, using definitions of extended functions and operators already provided. For example:

      APL
    q←3 2 4⍴⍳24 Reduced indent within the model.
    ,⍤1 2 q
 0  1  2  3  4  5  6  7
 8  9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
Ravel along axes 1 2
    f←,⍤1 2

    f q
 0  1  2  3  4  5  6  7
 8  9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
Assign the name f to this ravel
    ⍝→ An expression preceded byis
executed in raw APL; this exits

The function APL and its main supporting function are defined as follows:

APL;Z;X;NORE;⎕ps
NORE←<< 0 2 3 5 7 ⍴0×⎕ps← ¯1 ¯1 0 3
L1:→(^/' '=X←⍞,⍞←'    ')/L1
→('⍝'≠1↑X←(+/∧\' '=X)↓X)/L2
⍎1↓X
→L1
L2:Z←(X←TK X) S ''
→('←'=''⍴,>1↑(N X)/X)/L1
→L1,0⍴⎕←⍎((0=⍴⍴>Z)/'>'),'>Z'

Z←L S R
Z←⍎,>ACT[''⍴AC R]

The main action is the application of the stack manager S to an empty right stack and a left stack of enclosed individual tokens (names, primitives, constants, etc.) produced by the tokenizing function TK . The function S simply executes one of a set of actions represented in the vector ACT , selection from ACT being determined by the action and classes function AC , which in turn depends on the syntax table ST . The following display of ACT appears in enclosing bars because of ⎕ps←¯1 ¯1 0 ¯3 :

      ⍉,¨<ACT

|(>''⍴Z)S(1↓Z←L LE 4=1↑,⍴⍤>⍴¨>R),R|
|L S((>>R[0]) IS R[2]),3↓R|
|L S(2↑R),(R[2]RE R[,3]),4↓R|
|L S(1↑R),(R[1]RE R[,2],3↓R|
|L S(1↑R),(R[2]RE E R[1 3]),4↓R|
|L S(1↑R),(R[2]RE R[,1]),3↓R|
|⍎'R[1]',(2<⍴R)/'R not clear∘'|

In order to provide convenient tracing of the execution we incorporate in S three uses of a trace function TR as follows:

Z←L S R
Z←⍎,>ACT[''⍴' ACS' TR AC 'r: ' TR R],0⍴'l: ' TR L

The display produced by TR consists of its left argument followed by its right, except that the number of rows displayed is limited by the magnitude of the trace control variable t0 ; if t0 is positive, the display is suppressed (except for a blank line) if the left argument of TR begins (as it does in the first occurrence of TR) with a space. Finally, the display of a function is limited to its primary part, the body and axes. Thus:

      APL
    ⍝t0←1
    (÷4)+5
l:  |(| |÷| |4| |)| |+| |5|
r:
l:  |(| |÷| |4| |)| |+|
r:  ||5||
l:  |(| |÷| |4| |)|
r:  |||⍝<<(>>⍺)+>>⍵|| ||⍝<<+>>⍵||| ||5||
l:  |÷| |4|
r:
l:  |÷|
r:  ||4||
l:
r:  |||⍝<<(>>⍺)÷>>⍵|| ||⍝<<÷>>⍵||| ||4||
l:
r:  |⍝| |||⍝<<(>>⍺)÷>>⍵|| ||⍝<<÷>>⍵||| ||4||
l:
r:  |⍝| ||0.25||
l:
r:  ||0.25|| |||⍝<<(>>⍺)+>>⍵|| ||⍝<<+>>⍵||| ||5||
l:
r:  |⍝| ||0.25|| |||⍝<<(>>⍺)+>>⍵|| ||⍝<<+>>⍵||| ||5||
l:
r:  |⍝| ||5.25||
5.25

The five segments of this example beginning with l: |÷| |4| illustrate the recursive use of S to handle parenthesized expressions. The details of the representations of the functions ÷ and + (whose first lines appear in the displays of the right stack) may be ignored for the moment.

The “left evaluation” function LE handles the transfer of successive tokens from the input text to the righthand stack of intermediate results. Because the evaluated result in the right stack has no connection with the original names, the treatment of “side-effects” in expressions such as (a←3)(a←+)a←4 is clearly defined. For example:

    ⍝t0←0
    (a←3)(a←+)a←4
0.75
    a
3

The example may be repeated with t0 set to 1 .

The function LE normally evaluates each token and transfers the evaluated result to the right stack, but if the first element on the right stack is an assignment arrow, the evaluation is suppressed. For example:

    a←'bcd'
    ⍝t0←1
    a←a,a

l:  |a| |←| |a| |,| |a|
r:
l:  |a| |←| |a| |,|
r:  ||bcd||
l:  |a| |←| |a|
r:  |||⍝<<(>>⍺),>>⍵|| ||⍝<<,>>⍵||| ||bcd||
l:  |a| |←|
r:  ||bcd|| |||⍝<<(>>⍺),>>⍵|| ||⍝<<,>>⍵||| ||bcd||
l:  |a|
r:  |←| ||bcd|| |||⍝<<(>>⍺),>>⍵|| ||⍝<<,>>⍵||| ||bcd||
l:  |a|
r:  |←| ||bcdbcd||
l:
r:  ||a|| |←| ||bcdbcd||
l:
r:  ||bcdbcd||
l:
r:  |⍝| ||bcdbcd||

    ⍝t0←1
    a
bcdbcd
    ⍝→

A. Syntax

APL syntax questions may be characterized as old or new, the latter referring to the new questions raised by the general treatment of operators, and the former to old problems introduced by anomalies such as the treatment of brackets and semicolons in indexing, in axis operators, and in mixed output.

The old questions will here be treated as obsolescent, that is, nothing will be done to disturb existing definitions, either to invalidate their use in existing programs, or to extend them and encourage their use. The use of semicolons and brackets is therefore ignored in the model; in an actual implementation they could either be treated by established ad hoc mechanisms, or they could be eliminated by a “preprocessing” translation to equivalent normal expressions.

The new questions are addressed in the model by the action and classes function AC , which examines the stack of intermediate results to determine what action is to be taken next. In the syntax proposed here, this function depends only on the first four elements of the intermediate results, and depends only on the class of each of these elements.

The classes and their numeric encodings are as follows:

0  Variable
1  Monadic operator
2  Dyadic operator
3  Function
4  Assignment arrow
5  Left filler (exhaustion of the left stack, denoted in a trace by)
6  Right filler (exhaustion of the right stack)

The encodings of the first four correspond to the valences of the entities represented (allowing 3 as the sum of the potential valences of a function). They also correspond to the ranks of the arrays whose enclosures represent the entities. Consequently the expression ⍴⍤>⍴¨>⍵ occurring in the function AC determines the class of each element of the argument .

The syntax rules are, in effect, the manner in which the next action is chosen according to the classes of the intermediate result. This choice is made by the function AC (Action and Classes) in two steps:

1.   The classes of the first four elements of R (completed by the filler code 6) are matched with the rows of the first four columns of the symbol table ST , each individual comparison being negated if the element of ST is negative; thus an entry ¯2 designates anything except a dyadic operator.
 
2.   The first matching row selects the corresponding element of the last column of ST to be used (in S) as an index to the table of actions ACT . The classes are included in the result of the function AC only for use in tracing.

The proposed syntax table is defined as follows:

    ST
¯7  4 ¯7  6  1
 1  3  0 ¯7  3
 3  3  0 ¯7  3
 5  3  0 ¯7  3
 4  3  0 ¯7  3
 2  0  3  0  2
¯2  0  3  0  4
¯2 ¯1  2 ¯7  4
¯2 ¯1  1 ¯7  5
 5 ¯5 ¯7 ¯7  6
¯7 ¯7 ¯7 ¯7  0

However, it can be studied more easily in a display (produced by the function syntax) which substitutes for each numeric code a more mnemonic representation, and appends the corresponding action chosen from the table ACT . Thus:

      ⎕ps←-1 1 0 0
      i←((-7 5 3 2 1),⍳7)⍳0 ¯1↓ST
      c←11 7↑'aLFDMvmdf←lr'[i]
      c,⍕ACT[ST[;,4]]
a←ar   L S((>>R[0]) IS R[2]),3↓R
mfva   L S(1↑R),(R[1]RE R[,2]),3↓R
ffva   L S(1↑R),(R[1]RE R[,2]),3↓R
lfva   L S(1↑R),(R[1]RE R[,2]),3↓R
←fva   L S(1↑R),(R[1]RE R[,2]),3↓R
dvfv   L S(2↑R),(R[2]RE R[,3]),4↓R
Dvfv   L S(1↑R),(R[2]RE R[1 3]),4↓R
DMda   L S(1↑R),(R[2]RE R[1 3]),4↓R
DMma   L S(1↑R),(R[2]RE R[,1]),3↓R
lLaa   ⍎'R[1]',(2<⍴R)/'R not clear∘'
aaaa   (>''⍴Z)S(1↓Z←L LE 4=1↑,⍴⍤>⍴¨>R),R

The action and class codes produced by AC are displayed if the trace control is set to a negative value. For example:

      to←¯1
      APL
    a←3×4
l: |a| |←| |3| |×| |4|
r:
 acs|0| |6| |6| |6| |6|
l: |a| |←| |3| |×| 
r: ||4||
 acs|0| |0| |6| |6| |6|
l: |a| |←| |3|
r: |||⍝<<(>>⍺)×>>⍵|| ||⍝<<×>>⍵||| ||4||
 acs|0| |3| |0| |6| |6|
l: |a| |←|
r: ||3|| |||⍝<<(>>⍺)×>>⍵|| ||⍝<<×>>⍵||| ||4||
 acs|0| |0| |3| |0| |6|
l: |a|
r: |←| ||3|| |||⍝<<(>>⍺)×>>⍵|| ||⍝<<×>>⍵||| ||4||
 acs|4| |4| |0| |3| |0|
l: |a|
r: |←| ||12||
 acs|0| |4| |0| |6| |6|
l:
r: ||a|| |←| ||12||
 acs|1| |0| |4| |0| |6|
l:
r: ||12||
 acs|0| |0| |6| |6| |6|
l:
r: |⍝| ||12||
 acs|6| |5| |0| |6| |6|
    ⍝t0←0
    ⍝→

The proposed syntax is that embodied in the table ST , the selection function AC , and the list of actions ACT . Experiments with different syntax rules can be made by changes in any or all of these. Such changes can affect the number of elements R examined, or can even affect the classes and number of elements produced by the actions. Thus, an action could produce 0 or 2 or 3 results rather than 1 as proposed here, and the results could be operators as well as functions and variables. The table ST may be compared with the syntax table of [5], which covers the obsolescent syntax, but not the syntax of operators.

As stated in the introduction, parentheses are handled by an immediate recursive application of the model to the enclosed subexpression. With this premise, the remaining detailed syntax rules can be read directly from the display produced by the function syntax . However, the new features that extend the syntax to operators can be summarized as follows:

Operators take precedence over functions and have long left scope; that is, an operator applies to the result produced by the entire operator sequence to the left of it.
 

B. Representation of Functions and Operators

The primary definition of a function concerns the specification of what result it produces when applied to an individual array of the lowest rank upon which it is properly defined. However, the complete definition of a function also concerns certain attributes which determine the effects of applying various operators to the function. For example, the axis (or axes) of application is an attribute of a function which determines how the function applies to a higher-rank array, an attribute which is modified by an axis operator, as in ⌽[i]a ; the identity element of a function is an attribute that determines the result of the reduction operator in certain cases, as in +/⍳0 or ×/⍳0 .

The representation of functions adopted in the present model accommodates thirty attributes (of which 25 are actually used). The cases used are apparent from the following display of PF , the enclosed array (of shape 5 2 3) representing the prototype function:

      ⎕ps← -1 1 0 3
      >PF
|dbody|      |mbody|      |∘|
||7.237e75|| ||7.237e75|| ||7.237e75||

|loparg|     |roparg|     |∘|
|||⍺|||      |||⍵|||      |||⍵|||

||||         ||||         |∘|
|idf a¨∆|    |idf ∆¨a|    |idf ∆|

|dcase a¨∆|  |dcase ∆¨a|  |∘|
|a¨∆ ⍙|      |∆ ¨a⍙|      |∆⍙|

|variant0|   |variant1|   |∘|
|a¨∆*¯1|     |∆¨a*¯1|     |∆*¯1|

The significance of each of the positions in PF will be made clear in the discussion of the corresponding attribute.

The first plane of >PF is the primary definition, that is, the bodies of the dyadic and monadic cases, and the application axes. Bodies are represented in the direct definition form defined in [6], with three modifications:

1.   A leading indicates that what follows is to be executed in raw (i.e., conventional) APL rather than in the APL of the model. Comments are normally allowed in any segment of a direct definition, but because of the special use of the symbolthey are excluded from use in the model.
 
2.   A label is assigned a vector value consisting of the indices of all segments from the location of the label to the end of the definition.
 
3.   A name is localized only if it is immediately adjacent to an assignment arrow (and the mechanism for declaring globals is therefore not used).

The three axes accommodated are in the order left dyadic axis, right dyadic axis, and right monadic axis. The specification of axes is extended to include negative indexing (in which ¯1 denotes the ultimate axis, ¯2 the penultimate, etc.) and complementary indexing, in which a leading infinite value (denoted by the constant ¯ ) designates all axes except those in the vector following it. Thus, ¯ 2 4 ¯1 denotes all axes except 2,4, and the final axis, and ¯ alone denotes all axes. It may be noted that the axes specified in the prototype function are all of the latter type, making the standard, or default axes of application unbounded.

The operator(which will be discussed further in Section C), applied in the form f⍫∘ , produces a function that selects any desired section of the representation of a function f .

      APL
    d←+⍫∘
    d 0
||⍝<<(>>⍺)+>>⍵|| ||⍝<<+>>⍵|| |∘|
||||             ||||        ||||
    d 0 1
|||| |||| ||||
    +⍫∘ 0 0 0
||⍝<<(>>⍺)+>>⍵||

As seen in the foregoing, a single index selects a plane (the bodies and axes), two select a plane and a row, and three select a given element. Since a variable is represented by a double enclosure, the last display above shows that the dyadic definition of a function + is the (raw) double enclosure of + applied to the double disclosure of the arguments.

A monadic operator must be defined for two cases, a valence 0 argument (variable) and a valence 3 argument (function); a dyadic operator must be defined for four cases, two for each of its arguments. A monadic operator is therefore represented by an enclosed two-element vector, and a dyadic operator by an enclosed 2-by-2 matrix. For example:

    ⍤
|⍝⍺CONST⍵|     ||
|⍝⍺AXIS⍵⋄⍵←⊃⍵| |⍝⍺COMP⍵|

    ⌿
|| |⍝RED⍵|

    ∇
|⍝⍺DEL⍵| |∘|
|∘|      |∘|

An example of the detailed definition of an operator may be seen in the function DEL used in the direct definition operatorabove. Thus:

R←A DEL W
R←>PF
R[0;0; 0 1]←A,W
R[2;0; 0 1]←(<>A),<>W
R←<R

Briefly, the result of is the prototype function with the bodies replaced by the arguments of , and with the local names (in row 0 of plane 2) replaced by the names to be localized, as determined by applying the function LOC to each of the arguments of . For example:

      APL
    f←b×b←a ←⍺+⍵'∇'c*c←d ←÷⍵'
    2 f 5
49
    a
7
    f 2
0.7071
    d
0.5
    f⍫∘0 0
||b×b←a ←⍺+⍵|| ||c*c←d ←÷⍵|| |∘|
    f⍫∘2 0
|||b||| |||c||| |∘|
    b
value error
LE[2]⍎ b
       ∧

The details of other operators may be examined in a similar manner by displaying the supporting functions AXIS , COMP , etc. It may be noted that, although some of the definitions of operators must resort to functions in raw APL, some of the definitions may also be expressed in terms of operators defined only in the model. For example, the inverse operator con (denoted by) is defined as follows:

      APL
    ⊂
|| |⍵⍫i⍫⍵⍫(⌽i←''⊃4 1 2)|

C. An Auxiliary Definition Operator

An auxiliary definition operator, denoted byand used earlier in the form f⍫∘i to display position i of the representation of a function f , is introduced for the purpose of modelling, and is not proposed as an operator to be incorporated in the language in its present form. Two further eases of it will be used in subsequent sections:

a)   If f and g are functions, then f⍫g produces a function whose representation (of shape 10 2 3) is the catenation of the representations of f and g , as shown by the function D11 that produces it:
    D11 ⋄ <(>⍺),[0]>⍵

b)   If i is a vector whose two elements are enclosed indices (full or abbreviated), and if h←f⍫g , then h⍫i is the function defined by replacing the element (or sub-array) of the representation of f selected by the index >i[0] . Thus f⍫g⍫(2⍴<0 1) is the function f with its axes replaced by the axes of g . If h is a simple function (whose representation has shape 5 2 3), then h⍫i is equivalent to h⍫h⍫i .
 

D. Operator Arguments

Derived functions (resulting from the application of an operator) are represented in the general form presented in Section B; thus, the body and axes of ,⍤1 2 (ravel along axes 1 and 2) would appear as in the last two lines of the following example:

    APL
    f←,⍤1 2
    q←2 3 4⍴⍳24
    f q
 0  1  2  3  4  5  6  7  8  9 10 11
12 13 14 15 16 17 18 19 20 21 22 23
    F⍫∘ 0
||⍺F⍵|| ||F⍵||  ||∘||
||1 2|| ||1 2|| ||1 2||

The definition of a derived function depends upon the arguments of the operator which produced it, as well as upon the arguments to which it is applied; the arguments of the operator are referred to in the body by the names F and G , and are stored in locations 1 0 0 and 1 0 1 , that is, in the locations denoted by loparg and roparg in the prototype function PF . In the function f , the location 1 0 0 (that is, f⍫1 0 0) is the ravel function itself. Thus,

    17↑ f⍫ 1 0 0 q
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

The following example illustrates the important fact that the arguments of an operator are bound at the time of its execution, and that subsequent reassignments to the names to which it applied do not affect the derived function produced:

    r←,
    g←r⍤ 1 2
    r←⍴
    g q
 0  1  2  3  4  5  6  7  8  9 10 11
12 13 14 15 16 17 18 19 20 21 22 23
    r⍤1 2 q
3 4
3 4

Because of the binding at execution time, the inverse function (in location 4 1 2 , and denoted by ∆*¯1 in PF) must also appear explicitly in the representation of a function and cannot, in general, consist of a reference to the name of the inverse function. Since this inverse function must likewise contain (in its location 4 1 2) an explicit inverse function, the scheme seems to imply an infinite regression of explicit functions. However, because the inverse of the inverse is the original function, this implied difficulty can be handled in the simple manner shown in the following definition of an inverse operator:

    ⊂
|| |⍵⍫i⍫⍵⍫(⌽i←(<''),<4 1 2)|

The definition may be read as follows: ⍵⍫i produces a function in which the whole of the argument function (as selected by the empty first element of i) is replaced by element 4 1 2 of the same function, thus yielding the function inverse to . The further expression ⍵⍫i⍫⍵ therefore “catenates” the inverse ofwithitself, and the final application of ⌽i therefore inserts in location 4 1 2 of the inverse function , the original function. For example:

    l←* ⊂
    p←l ⊂
    l 3
1.099
    p⍫∘ 0 0 1
||⍝<<*>>⍵||

The analogous problem of explicitly representing successive derivatives of a function does not yield to the method applied for inverses, but can be handled by using the derivative location (3 1 2) to represent a dyadic function whose left argument k determines the order of the index; the index k will appear as the right operator argument (in location 1 0 1 , and referred to by G) and will be incremented on successive applications of the derivative operator.
 

E. Some New Functions

The convenience of the function representation employed will be illustrated by showing the formal definitions of some new functions:

    ⊢⍫∘0     Dex () - monadic is the identity function.
||⍵||        ||⍵||        |∘|
||7.237e75|| ||7.237e75|| ||7.237e75||
 
    ⊣⍫∘0 Lev () - monadic has no explicit result.
||⍺||        ||||         |∘|
||7.237e75|| ||7.237e75|| ||7.237e75||
    z←'abc'
    z
abc
    z←⊣'abc'
syntax error
IS[1]⍎ no result∘
                ∧

In the case of more complex functions, the axes of application may be seen even though the detailed definition of the body is subordinated in raw APL functions:

      APL
    {⍫∘0
||⍝<<(>>⍺)FR2>>⍵|| ||⍝<>⍵|| |∘|
||¯1||             ||7.237e75||  ||¯1||

In what follows we will use to denote a form of the link function that encloses its left argument and catenates it to the right, first enclosing the right argument if it is simple.

The foregoing function (called from) is defined briefly as follows: i{a is equivalent to inserting >i[j] before the jth semicolon of an expression of the form a[;;;…] . For example:

    m←4 4⍴⍳16
    (2 1⊃3){m
11 7
    (<2 1){m
 8  9 10 11
 4  5  6  7
    i←3 2⍴1 0 2 1 3 0
    i
1 0
2 1
3 0
    i{m
4 9 12

The final case of a simple array to provide “scattered” indexing results from the definition of the left axis of application.

The monadic case of { is the cartesian product. For example:

    { 2 1⊃4⊃6 7
2 4 6
2 4 7

1 4 6
1 4 7

The relation between the monadic and dyadic cases of the function { may be seen in the definition of the function FR2 .
 

F. Some New Operators

We will discuss only two operators, the first (to be denoted by } ) because it is both powerful and relatively unknown, and the second (denoted by ¨) because it motivates a number of attributes provided for in the representation of functions.

The first operator was introduced in [7] under the name til. It is defined as follows:

    }
|∘| |∘|
|∘| |'(G⍵)F⍺'∇'⍵∆⍵'⍫⍺⍫(1 0 0⊃⍳0)⍫⍵⍫(1 0 1⊃⍳0)|

The main function is seen in the expression '(G⍵)F⍺'∇'⍵∆⍵' ; the rest simply inserts the function argumentsandin the “operator argument” locations 1 0 0 and 1 0 1 .

The utility of til is discussed in [7]; the main point is that ⍺ f}g}h ⍵ ←→ (g⍺) f (h⍵) .

As defined in [1], the operator ¨ applied to one function and one array produces a monadic function resulting from providing the array as one argument to the dyadic function. For example, 10¨⍟ is the base 10 logarithm function, and *¨.5 is the square root function. As remarked in [7], two interesting points arise:

1.   Each of the monadic functions a¨f and f¨a may themselves possess inverses and derivatives; provision is made for these attributes in the locations labelled a¨∆*¯1 , ∆¨a*¯1 , a¨∆ , and ∆¨a in the prototype function PF .
 
2.   Because a derived function is ambivalent, provision is made (in locations 3 0 0 and 3 0 1 of the representation of a function f) for representing the dyadic cases of the functions a¨f and f¨a . The dyadic case of the selection function i¨{ is particularly important, being defined as follows:
The result of b i¨{a is the array a with b merged into the portion selected by i . This function obviates indexed assignment. In order to obtain the effect of indexed assignment of a , one would write a←b i¨{a . Other dyadic selection functions may be treated analogously.

G. Indirect Addressing

In the normal execution of an APL expression, each of the vector of tokens of the expression (placed in the left stack L in the model) is “evaluated” and the result of the evaluation is transferred to the stack of intermediate results (R in the model). However, a token which immediately precedes an assignment arrow must be exempted from this rule, and must be transferred “without evaluation“. For example:

    a←'abc'
    ⌽a
cba
    a←5
    a
5
    abc
value error

Parentheses, however, imply that the enclosed expression is to be evaluated, and the result transferred to the stack of intermediate results. In an expression such as (a)←5 this rule conflicts with the stated rule for assignment and, in conventional APL, such an expression is treated as a syntax error.

The conflict can be resolved by prescribing an order for the application of the two rules. In the present model, the rule for parentheses is applied first, with the obvious and convenient consequences illustrated by the following sequence:

      APL
    a←'abc'
    (a)←5
    a
abc
    abc
5

Since the result of evaluating an APL expression may be an array of enclosed names, the notion can be extended as shown by the following example:

    n←<⍤>'abcd'
    n
|a| |b| |c| |d|
    m←4 3⍴⍳12
    (n)←m
    a
0 1 2
    d
9 10 11
    ⍝→

The detailed definition of this indirect assignment may be seen in the function IS :

W←A IS W;X;N1;B1
⍎(NORE≡W)/'no result∘'
→(1∊A∊<⍤>A)/L0
→0,0⍴A IS1 W
L0:A←(,A),[0.5],(>>W) NUC1(⍴⍴A)↓⍳⍴⍴>>W
L1:→(0=1↑⍴A)/0
X←A[0;]
A← 1 0 ↓A
→(1∊N1∊<⍤>N1←>X[0])/L2
→L1,0⍴N1 IS1 X[1]
L2:→L1,0⍴N1 IS X[1]

The auxiliary function IS1 is simple assignment, except for the fact that it handles assignments to graphic symbols as well as to names that are legitimate in raw APL. The function NUC1 encloses the “nuclei” determined by the axes specified by its right argument.

Some interesting consequences of the definition of IS are illustrated by the following sequence in which j is assumed to be predefined (as shown):

      APL
    b←<4 5 6
    b
|4 5 6|
    (<'c')←b
    c
4 5 6
    ⍝⎕ps←-2/1 3
    j
|¯¯¯¯¯¯¯¯¯| |¯¯¯|
||¯¯¯| |¯|| |bcd|
||abc| |b|| |___|
||___| |_||
|         |
||¯|   |¯||
||c|   |d||
||_|   |_||
|_________|

    (j)←j
    abc
abc
    d
d

Since expressions of the form used for indirect addressing proposed here are invalid in conventional APL, their introduction would produce no conflict. Their use would, however, conflict with a different proposed use of parentheses to the left of assignment to extend the use of indexed assignment to selection functions other than “bracket” indexing [3]. It should be noted that the dyadic “merge” function i¨{ discussed in Section F illustrates a general scheme for using the operator ¨ together with any selection function to provide the effect of indexed assignment. It should also be noted that the explicit result of the expression b i¨} a is the entire merged entity, whereas the explicit result of a[i]←b (or of corresponding extensions to other functions) is simply b .
 

H. Index Origin

A number of people (among whom Professor Penfield is perhaps the most persuasive) have long maintained that any benefits provided by the choice of index origin in APL are outweighed by the burden of controlling its effects. It is, of course, futile to propose that the present use of index origin be changed in any way; however, in the design of any new functions and operators one may choose to exclude dependence upon index origin, just as the choice was made in the design of APL\360 [8] to exclude dependence on index origin in the definition of the residue function, even though the earlier definition in [9] included it.

Problems due to index origin appear to be magnified in the case of operators. For example, in g←f⍤i , are the axes used in the application of g to depend upon the origin in effect at the time of specifying g or at the time of applying g ? Or should it perhaps depend upon the index origins localized within the definitions of f and g as well?

In any case, the present proposal is to adopt a fixed index origin for all new functions and operators and to make this origin zero.
 

I. Idiosyncracies of the Model

For practical reasons the model has not been made as general as it could be, and any person using or modifying it should perhaps be aware of some of the limitations and peculiarities, and some of the reasons for them. Thus:

1.   Except for the name APL , the names used within the model all incorporate underscored letters [ed. note: uppercase letters in this text] or digits; the names that a user may safely employ should be formed from the simple alphabet only.
 
2.  

Some of the definitions of functions and operators are couched in expressions in raw APL, some in the extended APL provided by the model, and some in a mixture of the two. The choice of one or the other is rather arbitrary, except for the application of the following criteria:

   

a) Some of the underlying functions had to be expressed in raw APL in order to obtain a working model.

b) Illustrations of both uses were included as guides for anyone attempting to add further definitions.

c) Use of raw APL leads to more efficient execution of the model.

d) Use of the extended functions was very helpful in exercising the model and ensuring its correct behaviour.


3.   The main criteria applied in the design of the model were clarity and flexibility; increased efficiency can, if required, be attained by rewriting a number of the auxiliary functions.
 
4.   The definitions of the primitive functions provided in the model are incomplete in the sense that many of the meaningful attributes are left unspecified. However, the discussion and the examples (such as the inverse specified for the function *) should provide sufficient guidance for completing the definitions as desired.
 
5.  

The prototype function PF shown in Section B shows some attributes which have not been discussed. They should be considered as tentative.

For example, positions 1 0 show the argument names used, and an operator for changing them would allow a choice of the argument names to be used in the direct definitions. Similarly, positions 2 0 0 and 2 0 1 may be used to directly specify the names local to the dyadic and monadic cases.

Positions 2 1 provide for the specification of identity functions (as a generalization of identity elements) for the monadic function itself () and for each of the derived monadic eases a¨∆ and ∆¨a . Positions 4 0 0 and 4 0 1 provide for possible inclusion of variants of the type discussed in [10].

In specifying the inverse of any function it should be remembered that the specification is formal in the sense that it merely determines the function that results from the application of the inverse operator; the function may in fact be only a partial inverse (as in ¯1○⍵ and 1○⍵) or it could even be a function that is not inverse at all. Similar remarks apply to derivatives.
 

Acknowledgements

I am indebted to a number of my colleagues at I.P. Sharp Associates, particularly to Arthur Whitney for material adapted from his earlier model, and to Roland Pesch for comments arising from his use of the model.
 

References

1. R. Bernecky and K.E. Iverson, Operators and Enclosed Arrays, APL Users Meeting, I.P. Sharp Associates, October, 1980.
2. Carl Cheney, APL*PLUS Nested Arrays Reference Manual, STSC Corporation, 1981.
3. APL Language Manual, Form number SB21-3015, IBM Corporation, 1982.
4. P.K. Wooster, “Improved Display for Enclosed Arrays and a New System Variable ⎕ps”, Technical Supplement 37, I.P. Sharp Newsletter, Vol. 10, Number 2, 1982.
5. Third Working Draft of the International Standard for the Programming Language APL, International Standards Organization, ISO TC97/SC5/WG6-N28, 1982.
6. K.E. Iverson and P.K. Wooster, A Function Definition Operator, APL Quote Quad, Vol. 12 Number 1, ACM 1981.
7. K.E. Iverson and A.T. Whitney, Practical Uses of a Model of APL, APL Quote Quad, Volume 13, Number 1, ACM September 1982.
8. A.D. Falkoff and K.E. Iverson, APL\360, IBM Corp., November 1966.
9. K.E. Iverson, A Programming Language, Wiley, 1962.
10.   K.E. Iverson, Operators and Functions, Research Report RC 7091, Research Division, IBM Corp., 1978.

Appendix

See the body of the paper for functions APL , S , DEL , D11 , and IS , for variables ST , ACT , and PF , for operators , + , and , and for descriptions of variables P and t0 .

• Variables

      M
Z1←DE DEX Q;SC;SG;FS;J;Z;AR;⎕trap
⎕trap←'∇ 8 c →L0',0⍴Z←>DE[2]
⍎(>>''⍴⌽AR←>DE[1]),'←''''⍴⌽Q',(⍴Z) SLB Z
⍎(1≠⍴Q)/(>>''⍴AR),'←''''⍴Q'
SC←¯1⌽⍳⍴SG←>''⍴DE
L0:→(0=SC)/L4
SC←1↓SC,0⍴FS←>SG[''⍴SC]
→(∧/' '=FS)/L0
→('⍝'=1↑FS←(J←'→'=1↑FS)↓FS)/L1
→J↓L2,L3,0⍴Z←(TK FS) S ''
L1:→J↓L2,L3,0⍴Z←⍎1↓FS
L2:→L0,0⍴Z1←Z
L3:→L0,SC←,>>Z
L4:⎕trap←'∇ 6 C →0,0⍴Z1←NORE'
Z1←Z1

      CN
abcdefghijklmnopqrstuvwxyzABCDEFG
HIJKLMNOPQRSTUVWXYZ0123456789⎕¯.a

• Functions

AC⋄(1↑(∧/0>Z)≠(|Z)=(⍴Z←0 ¯1↓ST)⍴X)⌿ST[;4]),X←4↑(,⍴⍤>⍴¨⍵),4⍴6

z←f AXIS i;j
z←>''⍴PF,0⍴j←(<<'⍺F⍵'),(<<'F⍵'),(<<'∘')
z[0;;]← 2 3 ⍴j,<¨>3⍴>>i
z[1;0;0]←f
z←<z

CF⋄0≠⍴⍵,0⍴⎕ps←1⋄''⋄(⍎(⍺/'<,⍕'),',>1↑W'),(~⍺)CF 1↓⍵

CO⋄(1↑L)CF(L←'∧/⎕vi ⍵'ONA⍵)ENC⍵←⍵

z←a COMP b;q;j
q←>''⍴b,0⍴z←>PF
q[0;1;]←3⍴<⌊/0⍴j←(<<'(G⍺)F G⍵'),(<<'F G⍵')
z[1;0; 0 1]←a,b)[0;1;]
z←<z

more stuff here

TA⋄'(2×~(IQ ⍵)∨⍵∊CN)ENC ⍵'ONA(IQ⍵)ENC⍵

r←a TR r;k;l;z
→(0=k←|l←>>t0)/0
z←(¯2↑1,⍴z)⍴z←⍕(t←, 0 1 ↓m←(s∊⍴¨>PF)⌽(<1,
  2⌊k),2),[0.5] s←⍴¨>r)↑¨>r
((0>l)∨' '≠1↑a)/((k,⍴,a)⍴a),((k←k⌊1↑⍴z),¯1↑⍴z)↑z

z←a UPON b;q
z←>PF
q←(b←>b)[0;1;]
b[0;1;]←3⍴<<⌊/⍳0
z[1;0; 0 1]←a,<b
z[0;;]← 2 3 ⍴(<'F⍺G⍵'),(<'F G⍵'),(<<'∘'),q
z←<z

• Operators

      ⍫
||       |⍝⍺D01⍵|
|⍝⍺D10⍵| |⍝⍺D11⍵|

      ⍥
|∘| |∘|
|∘| |⍝⍺UPON⍵|


Originally appeared in the APL83 Conference Proceedings, APL Quote Quad, Volume 13, Number 3, 1983-03.

created:  2010-01-22 09:30
updated:2013-09-30 07:30