Formal Function Definition

Kenneth E. Iverson
 

This chapter concerns the scheme of formal function definition introduced in Section 1.3. In includes exercise which apply the basic scheme to a number of topics familiar in elementary mathematics. It also extends the basic schemes to include recursive definition, a form of definition which makes it easy to handle the formal definitions such as the quotient of polynomials. Section 10.3 defines a comprehensive set of functions for handling polynomials.

[The point at which each group of exercises can be attempted is indicated by a marginal note consisting of a domino () followed by the number of the first exercise in the group. The groups are separated by horizontal lines.]
 

10.1 Variables in a Function Definition

The expression defining a function may include one or more variables; these variables must, of course, be assigned values before the function is executed. For example:

      h:⍺×⍵*n
      n←2                         n←3
      3 h 4                       3 h 4
48                          192
                                                              ⌹1

Local variables. Consider the following function definition:

      m:1+(⍺-⍵)×2+(⍺-⍵)×3+(⍺-⍵)×4
      3 m 1
49

Since the expression ⍺-⍵ occurs repeatedly, it would be convenient to assign a variable name to the result ⍺-⍵ and use it in all positions, as follows:

      p:1+x×2+x×3+(x←⍺-⍵)×4
      3 p 1
49

The assignment of a value to the variable must be executed before (and therefore occur to the right of) any use of the variable. Thus, the following definition would not work, and attempted use of the function on a computer would invoke a value error message:

      q:1+(x←⍺-⍵)×2+x×3+x×4

A variable which is assigned a value within a function definition is local to the function in the sense that it has meaning only within the execution of the function and has no effect on assignments made outside the function. For example:

      x←7
      3 p 1
49
      x
7
                                                             ⌹13

10.2 Recursive definition

A function definition is said to be recursive if the function being defined recurs in the expression defining it. This notion may be familiar from informal definitions. For example, the power function x*n may be said to equal x times x*n-1 , and the factorial function !n may be said to equal n×!n-1 .

Let us attempt to define the factorial function fac in this manner:

      fac:⍵×fac ⍵-1

To interpret the expression fac 4 we would proceed by substitution as usual:

      fac 4
      4×fac 3
      4×3×fac 2
      4×3×2×fac 1

It is clear that this procedure can be terminated meaningfully only if we know the value of fac x for some value of the argument x . In this case, fac 1 is equal to 1 , and with this knowledge we can terminate the interpretation as follows:

      4×3×2×1
      24

In general, it is necessary to know a second expression for the definition (in this case the simple expression 1) and the condition under which it is to be applied (in this case when ⍵=1). The recursive definition of factorial therefore requires the following three pieces of information:

The primary expression: ⍵×f ⍵-1
A proposition: ⍵=1
A secondary expression: 1

In a formal definition these three data are presented in the foregoing order with colons separating them. Thus:

      fac:⍵×fac ⍵-1:⍵=1:1

      fac 4
24

A proposition is a function which yields one of two values, 0 (representing false) or 1 (representing true). In a recursive definition the proposition is executed first; its result determines which defining expression is to be used, the primary if the result is 0 , and the secondary if the result is 1 . The secondary expression must not include within it the function being defined.

A more suitable definition of the factorial function would, in fact, include the argument 0 as follows:

      fac:⍵×fac ⍵-1:⍵=0:1

A recursive definition of the power function which is equivalent (for non-negative integer arguments) to ⍺*⍵ could be made as follows:

      pow:⍺×⍺ pow fac ⍵-1:⍵=0:1

The interpretation of 2 pow 3 would proceed as follows:

      2 pow 3
      2×2 pow 2
      2×2×2 pow 1
      2×2×2×2 pow 0
      2×2×2×1
      8

Many functions which are difficult to define in other ways are easy to define recursively. Moreover, many functions easily defined in other ways may profitably be defined recursively, since the recursive definition may provide better understanding of certain properties of the function.

⌹16

10.3 Functions for Handling Polynomials

This section is intended to provide further examples of both recursive and non-recursive function definitions, and to illustrate the development of a coherent set of functions for the treatment of a single topic. The topic chosen is that of polynomials expressed in the form introduced in Section 1.5.

The basic notion is to represent a polynomial in terms of its vector of coefficients. For example, if the coefficients are 3 1 4 2 and x←2 , then the value of the polynomial is given by:

      +/3 1 4 2×x*0 1 2 3
37

The definition of the polynomial function (given in a slightly different form in Equation 1.5.1) is therefore:

      p:+/⍺×⍵*⍳n ⍺

where n yields the number of elements in its argument, and is defined as follows:

      n:+/⍵=⍵

For example:

      x←2
      c←3 1 4 2
      n c
4
      ⍳n c
0 1 2 3
      c p x
37
      1 3 3 1 p 2
27

If d←1 3 3 1 then the sum of the polynomials with coefficients c and d is given by:

      (c p x)+d p x
64

Moreover, the polynomial with coefficients c+d has the same value:

      c+d
4 4 7 3
      (c+d) p x
64

If the vectors c and d do not have the same number of elements, the expression c+d will not yield the sum; it is necessary to extend one of them by final zeros (which do not change the value of the polynomial represented). Addition of the vectors of coefficients of two polynomials can be performed by the following function:

      plus:(ml↑⍺)+(ml←(n⍺)⌈n⍵)↑⍵

      c←3 1 4
      d←1 2 3 4 5
      c plus d
4 3 7 4 5
      d plus c
4 3 7 4 5
      (c plus d) p 2
150
      (c p 2)+d p 2
150

A function for the subtraction of polynomials could be defined similarly, but it is clearer and simpler to use the function plus in its definition:

      minus:⍺ plus -⍵

      c minus d
2 ¯1 1 ¯4 ¯5

An informal scheme for multiplying polynomials is developed in Section 1.7, and is formalized in Ex 1.74. An equivalent function is provided by the following recursive definition (whose details can be made clear by working through the detailed substitutions of a simpler example):

      times:(⍺×1↑⍵) plus 0,⍺ times 1↓⍵:0=n⍵:0
      1 2 1 times 1 3 3 1
1 5 10 10 5 1
      (1 2 1 times 1 3 3 1) p 3
1024
      (1 2 1 p 3)×1 3 3 1 p 3
1024
                                                             ⌹24

Division of one polynomial by another is effected by the following function:

      into:z,⍺ into 1↓⍵ minus ⍺×z←(1↑⍵)÷1↑⍺:(n⍺)>n⍵:⍳0

      a←1 2 1
      b←1 5 10 10 5 1
      c←0 0 0 0 2 8
      d←b plus c
      d
1 5 10 10 7 9
      a into b
1 3 3 1
      a into d
1 3 3 1
      rem←d minus a times a into d
      rem
0 0 0 0 2 8

From the foregoing example, it appears that the division performed by into yields a high-order remainder, as defined in Section 1.7. A similar definition could be made for a lower-order division function, but it is easier to define it in terms of into as follows:

      linto:⌽(⌽⍺) into ⌽⍵
      a linto b
1 3 3 1
      a linto d
¯25 23 ¯11 9
      rm←d minus a times a linto d
      rm
26 32 0 0 0 0

Considered as a coefficient vector, the last result above is equivalent to the vector 26 32 . It may be convenient to define a function which will curtail any vector by dropping all final zeros:

      curt:(-+/⌊\0=⌽⍵)↓⍵
      curt rm
26 32

A polynomial with coefficients 1 , or 1 0 , or 1 0 0 , etc., has the value 1 for all values of its argument. Hence a polynomial which is (for small values of its argument) an approximate reciprocal of a given polynomial, can therefore be obtained by dividing the given polynomial into a polynomial of the form 1 followed by zeros. For example:

      v←20↑1
      v
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      a←1 1
      ar←a into v
      ar
1 ¯1 1 ¯1 1 ¯1 1 ¯1 1 ¯1 1 ¯1 1 ¯1 1 ¯1 1 ¯1 1
      ar p .5
0.6666679382
      ÷a p .5
0.6666666667
      b←1 2 1
      br←b into v
      br
1 ¯2 3 ¯4 5 ¯6 7 ¯8 9 ¯10 11 ¯12 13 ¯14 15 ¯16 17 ¯18
      br p .5
0.4443969727
      ÷b p .5
0.4444444444

The function p:+/⍺×⍵*⍳n⍺ applies only to a scalar right argument and fails to work properly on a vector right argument, for reasons that may be seen in attempting to evaluate 1 3 3 1 p 2 5 or 1 3 3 1 p 2 5 7 9 .

A corresponding function which applies to a vector right argument may be defined recursively as follows:

      pvra:(⍺ p 1↑⍵),⍺ pvra 1↓⍵:0=n⍵:⍳0
      1 3 3 1 pvra 2 5
27 216
      1 3 3 1 pvra 2 5 7 9
27 216 512 1000

The entire set of functions developed for handling polynomials is collected below:

      p:+/⍺×⍵*⍳n⍺
      n:+/⍵=⍵
      plus:(ml↑⍺)+(ml←(n⍺)⌈n⍵)↑⍵
      minus:⍺ plus -⍵
      times:(⍺×1↑⍵) plus 0,⍺ times 1↓⍵:0=n⍵:0
      into:z,⍺ into 1↓⍵ minus ⍺×z←(1↑⍵)÷1↑⍺:(n⍺)>n⍵:⍳0
      linto:⌽(⌽⍺) into ⌽⍵
      curt:(-+/⌊\0=⌽⍵)↓⍵
      pvra:(⍺ p 1↑⍵),⍺ pvra 1↓⍵:0=n⍵:⍳0
                                                             ⌹25

10.4 The Function def

Throughout this text, function definitions have been presented in the ⍺⍵ form introduced in Section 1.3 and elaborated in Section 10.1. In order to make any function so defined available for use on an APL computer it is necessary to fix the definition. The function def has been assumed to perform this function: if it is already available in the computer it may be used as shown in Section 1.4; if not, its definition must itself be fixed before it can be used.

This section discusses the steps necessary to develop and fix the function def . If it is simply desired to fix the definition def as quickly as possible, the reader may follow the summary steps at the end of this section. On the other hand, the section may be studied as a whole for its own interest since it clarifies the important notion of representation, and uses and exemplifies the important technique of “bootstrapping”. This term arises from the paradoxical notion of “pulling yourself up by your own bootstraps”, and is used here to refer to the scheme of using a function already fixed as a tool in developing and fixing the next one.

In the course of this process, several functions are produced which can be used to fix the definitions of certain functions, but all except the function def defined at the end are deficient in some respect, and will fail to work in certain cases. For example, the function is9 will work only on simple (non-recursive) definitions.

The essential service performed by the function def is to transform the ⍺⍵ representation of a function into a form directly usable by the APL computer. Since we will be concerned with different representations of a function, we shall first attempt to clarify the notion of representation, beginning with the more familiar notion of different representations of numbers.

The representation of numbers. Numbers are commonly represented by strings of numeric characters, just as words are represented by strings of alphabetic characters. Thus the numeric characters 1 and 4 and 4 strung together represent the number of items in a gross, just as the letters M and a and r and y together represent a name.

Confusion can sometimes arise if we fail to distinguish a representation from the thing represented. For example, the sentence Mary has four letters could refer either to the volume of a girl’s correspondence or to the length of her name. The necessary distinction is normally made by enclosing the alphabetic characters in quotes when referring to the representation itself. Thus the sentence 'Mary' has four letters is unambiguous, and refers to the length of a girl’s name.

In the case of numbers, the need to distinguish between a number and its representation does not arise very often, and it therefore tends to be particularly confusing when it does. We will also use quotes to enclose numeric characters; thus '144' and '10010000' and 'CXLIV' are each a character string representing the number of items in a gross, the first representation being in decimal, the second in binary (base two), and the last in Roman numerals.

Just as we cannot truthfully say 'Mary' can walk , neither can we add '144' to '1024' , although we can say Mary can walk , and we can add 144 to 1024 . This distinction can be clarified by considering the execute function (denoted by); applied to a numeric character string it yields the number represented by the string. For example:

      (⍎'144')+⍎'1024'
1168
      '144'+'1024'
DOMAIN ERROR

More generally, the execute function applied to any character string treats it as an APL expression and executes (that is, evaluates) it. For example:

      ⍎'144+1024'
1168
      ⍎'Mary←144+1024'            b←⍎'144+1024'
      Mary                        b
1168                        1168  

Just as names can be assigned to numeric quantities, so can they be assigned to character strings. For example:

      a←'144'
      b←'1024'
      (⍎a)+⍎b
1168

A character string of n characters can be treated much like a numeric vector of n elements (or as a scalar if n is 1). For example, the vectors a and b specified above can be catenated:

      a,b
1441024
      ⍎'c←',a,'+',b
      c
1168

Other functions which select from or reshape an array can also be applied to character vectors. For example:

      m←'Mary'
      n←'2157'
      ⌽n                          m,n
7512                        Mary2157
      m[0 3]                      2 4⍴m,n
My                          Mary
                            2157

It should be noted that a character string does not include the quote marks used in entering it. Moreover, a quote mark to be included in a character string must be denoted by a pair of quotes together. Thus if c←'can''t' then c is the contraction of the word cannot, and:

      c                           +/c=c
can't                       5
                                                             ⌹29

Representation of functions. We may now say that a function in the form ⍺⍵ is represented by a character string. For example, the function for the square root called sqrt is represented by the nine-character string 'sqrt:⍵*.5' .

Just as representations other than the decimal may be used for numbers, so other representations may be used for functions. For example, the function represented by f:⍵+⍺×⍵*2 could also be represented by the expression:

      c+p×c*2

together with something which indicates the name of the function and which name in the expression represents the first argument and which the last. This information could be indicated by the string p f c , and the whole could be represented by a matrix:

      m←2 7⍴'p f c  c+p×c*2'
      m
p f c  
c+p×c*2

Every function defined in this text (and most functions of interest in mathematics) produce a result. In order to permit the definition of functions which do not produce explicit results (a matter which need not otherwise concern us here), the form of function representation used in an APL computer includes explicit mention of the result. The actual representation for the function f:⍵+⍺×⍵*2 therefore takes the form:

      m←2 9⍴'z←p f c  z←c+p×c*2'
      m
z←p f c  
z←c+p×c*2

This form of representation is called a canonical representation.

A function represented in canonical form can be established or fixed (and thus made available for use) by applying the system function ⎕fx to the matrix m which represents the function. Thus:

      ⎕fx m
f
      2 f 3
21

The foregoing example shows that in addition to fixing the function represented by its argument m , the function ⎕fx produces as an explicit result the character string which represents the name of the function.

The canonical representation of a monadic function is similar; the left argument is omitted from the first row. For example, the function sub9:⍵ can be established as follows:

      n←2 8⍴'z←sub9 yz←y     '
      n
z←sub9 y
z←y     
      ⎕fx n
sub9
      sub9 7
7
                                                             ⌹33

Name conflicts. In what follows we will be establishing certain functions for use as tools in defining other functions; the names for these tools must not conflict with the names of functions which we may wish to establish. For example, if one of our tools is called on , and we use it to establish a new function called on , the tool function itself may be destroyed.

For each tool function we will therefore use a name with the digit 9 as the last character and assume that the user of the tool will not try to establish any functions with such a name. The names chosen will otherwise be as mnemonic as possible, such as is9 , and on9 .

The xy form of function definition. We will now consider a third form of function definition which is easy to produce mentally from an ⍺⍵ definition (by simple substitutions) and which is rather easy to translate mechanically (by simple functions which will now be developed) to canonical form and to then fix. This xy form will then be used as a convenient way to define the further functions needed to translate directly from the ⍺⍵ form.

The xy representation of a function called plus which sums its arguments is simply:

      'plus' is9 'x+y'

The translation from ⍺⍵ form to the xy form is obvious:replace eachby x and eachby y , enclose the prefix (which precedes the colon) and the suffix (which follows the colon) each in quotes, and replaced the colon by is9 .

We will now develop and fix a function is9 which will perform as required. This function can achieve its purpose in the following steps:

1.  Form the arguments into a two-rowed matrix by placing the first on top of the second.
2.  Append the symbols z andand y and (if the function is dyadic) x so as to form the canonical representation of the specified function.
3.  Apply the function ⎕fx to the resulting matrix so as to fix the desired function.

Step 1 can be performed by the function

      on9:(2,m9)⍴(m9↑⍺),(m9←(+/⍺=⍺)⌈+/⍵=⍵)↑⍵

In xy form this becomes:

      'on9' is9 '(2,m9)⍴(m9↑x),(m9←(+/x=x)⌈+/y=y)↑y'

The matrix m obtained by step 1 would be:

      m
on9
(2,m9)⍴(m9↑x),(m9←(+/x=x)⌈+/y=y)↑y

However, we do not yet have the function is9 established, and we must somehow produce the matrix m using neither is9 nor on9 . This can be done by entering the following expression:

      m←2 34⍴(34↑'on9'),'(2,m9)⍴(m9↑x),(m9←(+/x=x)⌈+/y=y)↑y'

Step 2 in the establishment of the function on9 must also be performed using neither is9 nor on9 . This can be done by first specifying a matrix q as follows:

      q←2 6⍴' yz←x   z←  '
      q
 yz←x 
  z←  

The expression n←2⌽q,m will now make n the canonical representation of the function on9 :

      n
z←x on9                                y
z←  (2,m9)⍴(m9↑x),(m9←(+/x=x)⌈+/y=y)↑y  

The function on9 can now be established:

      ⎕fx n
on9

Since the function on9 is now established it can, and will, be used in what follows.

⌹36

The function on9 performed step 1, and it remains to treat steps 2 and 3. The treatment of step 2 is suggested by the matrix q used in defining on9 , but this matrix contains the character x and is suited only for dyadic functions. We begin, therefore, by defining a matrix ar9 (for argument and result names) as follows:

      ar9←3 7⍴'   z←   y z←   y z←x '
      ar9
   z←  
 y z←  
 y z←x 

If g9←'xy' , then the expression ⌈/g9∘.=y yields a two element vector; the first element is 1 if the character x occurs in y and zero otherwise, the second is 1 if the character y occurs in y . Therefore the expression +/⌈/g9∘.=y determines the number of arguments in the expression represented by the vector y . Consequently, the expression ar9[1 0×+/⌈/g9∘.=y;] selects from ar9 the matrix appropriate to the number of arguments. For example, ar9[1 0×2;] yields a matrix similar to the matrix q used in the definition of on9 .

Step 2 (producing the canonical form) can now be achieved by the expression 3⌽ar9[1 0×+/⌈/g9∘.=y;],m where m is the result of step 1. The representation of the necessary function (can9) itself is therefore given by:

      g9←'xy'
      m←'can9' on9 '3⌽ar9[1 0×+/⌈/g9∘.=y;],x on9 sub9 y'

The function can9 may now be fixed and used as follows:

      ⎕fx 3⌽ar9[2 0;],m
can9
      'pol' can9 '+/x×y*⍳+/x=x'
z←x pol          y 
z←  +/x×y*⍳+/x=x   

It should be recalled that the function sub9 used in the definition of can9 above (and defined earlier) yields its argument unchanged. The point of including it in can9 is that sub9 will later be redefined to substitute x for and y for , and the other functions to be defined (which use can9) will then work on definitions in the ⍺⍵ form.

⌹38

We now complete the process by defining, and illustrating the use of, a dyadic function is9 which takes two arguments, a function name and the defining expression, and fixes the appropriate definition:

      c←'is9' can9 '⎕fx x can9 y'
      ⎕fx c
is9
      'pol' is9 '+/x×y*⍳+/x=x'
pol
      1 3 3 1 pol 4
125
                                                             ⌹40

The function is9 takes two arguments, the name and the defining expression. We will now define a function sdef9 (for simple as opposed to recursive definitions) that applies to an argument which is in the ⍺⍵ form except that the charactersand are replaced by x and y . We begin by defining (and illustrating) a prefix function p9 and a suffix function s9 which select the parts of an expression preceding and following the first colon. We will use the variable h9 to denote a colon:

      h9←':'
      'p9' is9 '(+/⌊\y≠h9)↑y'
p9
      's9' is9 '(1++/⌊\y≠h9)↓y'
s9
      y←'hyp:((x*2)+y*2)*.5'
      p9 y
hyp
      s9 y
((x*2)+y*2)*.5
      (p9 y) is9 s9 y
hyp
      3 hyp 4
5

The scheme used for defining the function hyp above suggests the following definition for sdef9 :

      'sdef9' is9 '(p9 y) is9 s9 y'
sdef9

For example:

      sdef9 'plus:x+y'
plus
      3 plus 4
7
                                                             ⌹41

Recursive definitions. The expression y←'f:y×f y-1:y=0:1' represents a recursive definition of the factorial function in xy form. The three components can be selected by using the prefix and suffix functions p9 and s9 :

      p9 y                        p9 s9 y
f                           y×f y-1
      p9 s9 s9 y                  s9 s9 s9 y
y=0                         1

The following expression will execute the third component (y=0) and use the result to select the second (y×f y-1) or the last (1) for execution:

      ⍎((0=y=0)/'y×f y-1'),(0≠y=0)/'1'

If we underscore the parts taken from the original expression, this appears as:

      ⍎((0=y=0)/'y×f y-1'),(0≠y=0)/'1'

and makes clear that the five unadorned portions are symbols added to the original expression. These five additions may be entered as variables as follows:

      a9←'⍎((0='                  d9←')/'''
      b9←')/'''                   e9←''''
      c9←'''),(0≠'

These variables may now be used to define a function form9 which forms the required expression:

      c←'form9:a9,(p9 s9 s9 y),b9,(p9 s9 y),c9'
      c←c,',(p9 s9 s9 y),d9,(s9 s9 s9 y),e9'
      sdef9 c
form9

For example:

      y←'f:y×f y-1:y=0:1'
      form9 y
⍎((0=y=0)/'y×f y-1'),(0≠y=0)/'1'

The function rdef9 (for recursive definition) can now be defined rather simply:

      sdef9 'rdef9:(p9 y) is9 form9 y'
rdef9

For example:

      rdef9 y
f
      f 5
120
                                                             ⌹43

All definitions. We now have a function sdef9 which treats simple definitions and a function rdef9 which treats recursive definitions. The can now be used to define a function adef9 which treats all definitions:

      rdef9 'adef9: sdef9 y:3=+/h9=y:rdef9 y'
adef9

For example:

      adef9 'div:x÷y'
div
      3 div 6
0.5
      adef9 'g:y×g y-1:y=0:1'
g
      g 6
720

Recall that the variable h9 was specified by h9←':' .

⌹44

The ⍺⍵ form. In order to make the function adef9 apply to definitions in the ⍺⍵ form it is necessary to substitute x forand y for . A function in9 will first be defined as:

      c←'in9:x in9(q9↑y),(1↓x),(1+q9)↓y:(+/y=y)=q9←+/⌊\y≠1↑x:y'
      adef9 c
in9

For example:

      '+ plus ' in9 '3+4×5+6'
3 plus 4×5 plus 6

For each occurrence in the right argument of the first element of the left argument, this function substitutes the remainder of the left argument.

The obvious substitutions can be carried out by the expression '⍺X' in9 '⍵y' in9 y . However, in the case where y defines a monadic function but contains onlybut not , it is first necessary to swapfor . The whole can be done as follows:

      i9←'⍺x'
      j9←'⍵y'
      k9←'⍺⍵'
      
      adef9 'sw9:k9 in9 y:1≠+/⌈/k9∘.=y:y'
sw9
      adef9 'sub9:i9 in9 j9 in9 sw9 y'
sub9

For example:

      sw9 'f:⍺×⍺'
f:⍵×⍵
      sw9 'f:⍺×⍵'
f:⍺×⍵
      sub9 'f:⍺+⍵'
f:x+y
      sub9 'f:⍺×⍺'
f:y×y
      adef9 'f:⍺+⍵'
f
      2 f 5
7
                                                             ⌹45

Argument conflicts and spaces. Names ending in 9 have been chosen for all of the functions and variables developed as tools. This avoids conflict with names used for the functions to be defined by them. There remains a potential conflict with the names x , y , and z used for arguments and results in the canonical forms of the functions defined.

Respecifying the values of i9 and j9 as:

      i9←'⍺ x9 '
      j9←'⍵ y9 '

causes the names x9 and y9 to be substituted forand rather than x and y . Moreover, the spaces before and after these names ensure that a space will separate them from other names even though such separation does not occur in the given expression, as in f:⍵×f⍵-1:⍵=0:1 .

The variable ar9 must also be respecified to provide the appropriate names for the canonical form:

      ar9←3 9⍴'   z9←    y9z9←    y9z9←x9 ' 
      ar9
   z9←   
 y9z9←   
 y9z9←x9 

With these changes the function adef9 will perform properly.

Character input. The function def was assumed to perform as follows:

      def
f:⍺+⍵

      3 f 4
7

The function adef9 differs in two respects:

1.  It products and prints the name of the function defined. This can be avoided by using the expression 0⍴adef y .
2. 

It requires that the expression be enclosed in quotes and accompany it on the same line. This can be avoided by using the expression adef9 ⍞ .

For example:

      0⍴adef ⍞
d:⍺-⍵

      6 d 4
2

The symbol(pronounced quote-quad) is simply replaced by the following entry considered as a character string. For example:

      x←⍞
abcd
      x,⌽x
abcddcba

The function def may therefore be defined as follows:

      adef9 'def:0⍴adef9 ⍞'
def

For example:

      def
fib:z,+/¯2↑z←fib⍵-1:⍵=1:1

      fib 7
1 1 2 3 5 8 13
                                                             ⌹47

The function def developed in this section will handle all of the functions discussed in Chapters 1 to 9. However, it does not localize variables as discussed in Section 10.1, and it fails to properly treat recursive definitions which include explicit quote marks.

Schemes for modifying the function def to handle local variables are discussed in exercises. However, problems due to the failure to localize variables can be largely avoided by choosing distinctive names for variables that should be localized, as was done with the choice of m9 in the definition of the function on9 . Problems due to quotes can be avoided by first assigning names to quoted strings so that the quotes do not appear explicitly in the function definition, as was done for h9 , and a9 , and others.

⌹48

Summary. The steps required in the definition of the function def are collected together on the following page, where they are shown together with the expected responses. If the expected response is not received, steps should be taken to obtain the correct response before proceeding further. Remember that if any error messages are printed it may be necessary to enter the symbolalone on a line one or more times before proceeding.

      )clear
clear ws
      ⎕io←0
      ⎕fx 2 8⍴'z←sub9 yz←y     '
sub9
      m←2 34⍴(34↑'on9'),'(2,m9)⍴(m9↑x),(m9←(+/x=x)⌈+/y=y)↑y'
      ar9←3 7⍴'   z←   y z←   y z←x '
      ⎕fx 3⌽ar9[2 0;],m
on9
      g9←'xy'
      m←'can9' on9 '3⌽ar9[1 0×+/⌈/g9∘.=y;],x on9 sub9 y'
      ⎕fx 3⌽ar9[2 0;],m
can9
      ⎕fx 'is9' can9 '⎕fx x can9 y'
is9
      h9←':'
      'p9' is9 '(+/⌊\y≠h9)↑y'
p9
      's9' is9 '(1++/⌊\y≠h9)↓y'
s9
      'sdef9' is9 '(p9 y) is9 s9 y'
sdef9
      a9←'⍎((0='
      b9←')/'''
      c9←'''),(0≠'
      d9←')/'''
      e9←''''
      m←'form9:a9,(p9 s9 s9 y),b9,(p9 s9 y),c9'
      m←m,',(p9 s9 s9 y),d9,(s9 s9 s9 y),e9'
      sdef9 m
form9
      sdef9 'rdef9:(p9 y) is9 form9 y'
rdef9
      rdef9 'adef9:sdef9 y:3=+/h9=y:rdef9 y'
adef9
      c←'in9:x in9 (q9↑y),(1↓x),(1+q9)↓y'
      c←c,':(+/y=y)=q9←+/⌊\y≠1↑x:y'
      adef9 c
in9
      i9←'⍺ x9 '
      j9←'⍵ y9 '
      k9←'⍺⍵'
      adef9 'sw9:k9 in9 y:1≠+/⌈/k9∘.=y:y'
sw9
      adef9 'sub9:i9 in9 j9 in9 sw9 y'
sub9
      ar9←3 9⍴'   z9←    y9z9←    y9z9←x9 '
      g9←'⍺⍵'
      adef9 'def:0⍴adef9 ⍞'
def

Exercises

10.1  Consider the following set of functions:
i) fti:12×⍵
ii) itf:(÷12)×⍵
iii) ytf:3×⍵
iv) yti:fti ytf ⍵
v) f:12×3×⍵
vi) g:⍵
vii) h:fti itf ⍵
viii) k:itf fti ⍵
ix) l:(fti itf ⍵)÷⍵
x) m:36+0×⍵
 
a)  For each function above, show its interpretation in detail by applying it to some argument. For example:
      fti 7
      12×7
      84
(This part need not be done for functions whose meaning is clear.)
 
b)  State clear but informally what each function does. For example, fti converts from measurements expressed in feet to measurements expressed in inches.
 
c)  Determine which among the functions are equivalent. For example, g and h are equivalent.
 
d)  State clearly any other relations you observe among the functions; for example, fti is the inverse of itf , and (f ⍵)÷g ⍵ equals the constant function m ⍵ .
 
10.2  Repeat Ex 10.1 for the following functions (all of which concern conversions between units of measurements).
i) itc:2.54×⍵
ii) cti:(÷2.54)×⍵
iii) ctf:32+1.8×⍵
iv) ftc:(÷1.8)×(-32)+⍵
v) f:ctf ftc ⍵
vi) g:⍵
 
10.3  Define functions for each of the following conversions of units:
a) Hours to minutes
b) Minutes to hours
c) Days to hours
d) Days to minutes
e) Minutes to seconds
 
10.4 

a) Which of the functions in Ex 10.3 are equivalent?

b) Do an interpretation of the function f of Ex 10.2 to show that it is equivalent to g .
 

10.5  Repeat Ex 10.1 for the following functions (which concern measures of simple geometric figures).
i) as:⍵*2
ii) ar:⍺×⍵
iii) at:.5×⍺×⍵
iv) vc:⍵*3
v) vsqpy:(÷3)×⍺×⍵*2
vi) ps:4×⍵
vii) pr:2×⍺+⍵
viii) sac:6×⍵*2
 
10.6  Repeat Ex 10.1 for the following functions (which concern measures of circles and spheres):
i) pitimes:3.14159×⍵
ii) ac:pitimes ⍵*2
iii) pc:2×pitimes ⍵
iv) dc:2×⍵
v) f:ptimes dc ⍵
vi) g:(÷4)×ac ⍵
 
10.7 

The monadic functionis defined (in Sec 4.10) as pi times its argument, that is, ○⍵ is (approximately) equivalent to pitimes ⍵ as defined in Ex 10.6.

a) Redefine each of the functions in Ex 10.6 replacing the function pitimes by .

b) Use the functionto define the following functions:

i) Volume of a sphere
ii) Surface of a sphere
iii) Volume of a circular cylinder (with first argument for height and second for radius).
iv) Function of part iii with arguments reversed.
v) Volume of a sphere using the function of part ii in its definition.
 
10.8 

Repeat Ex 10.1 for the following functions, all of which concern geometric figures:

i) v:×/⍵
ii) p:+/⍵
iii) sp:.5×p ⍵
iv) ttest:⌊/⍵≤ sp ⍵
 
10.9 

a) Apply the function ttest of Ex 10.8 to vectors l←2 5 4 and r←2 5 2 , and then try to construct triangles with lengths specified by l and by m .

b) Will ttest serve to check the suitability of a set of lengths for the sides of a polygon, i.e., for an argument of any number of elements?

c) Modify ttest to exclude degenerate polygons which enclose no area; for example, ttest 2 5 7 yields 1 , although these dimensions do not yield a proper triangle.
 

10.10 

a) Define a monadic function asc which applied to a scalar argument yields the surface area of a cube of dimension given by the argument.

b) Define a monadic function as which, when applied to a 3-element vector yields the surface area of the box represented by the vector.

c) Compare the results of asc n and as n,n,n for various values of the scalar n .
 

10.11 

a) Compare the function as defined in Ex 10.10 with the function a:2×+/⍵×⍵[1 2 0] .

b) Rewrite the expression for a in part a using the rotation function defined in Sec 5.8 instead of indexing.
 

10.12  Evaluate the function scale:r×⍵ for several arguments first with the ratio r←2.54 , and then with r←12 .
 


10.13 

a) Identify the class of triangles whose sides are given by applying the following function to non-negative integer arguments:

alrt:(|-/z*2)(+/z*2),2××/z←⍺,⍵

b) State the purpose of the following function:

testrt:(+/⍵*2)=2×(⌈/⍵)*2

c) The semi-perimeter function sp of Ex 10.8 can be used in Hero’s formula for the area of a triangle in terms of the lengths of its sides:

Hero:(×/(s-⍵),s←sp ⍵)*.5

Evaluate Hero 3 4 5 and Hero 1 1 1 and check that the results do represent the areas.

d) Show that the following function is equivalent to the function testrt of Ex 10.13:

q:(Hero ⍵)=.5×(×/⍵)÷⌈/⍵

10.14 

Repeat Ex 10.1 for the following functions:

si:+/z←1+⍳⍵
sis:+/z×z←1+⍳⍵
sic:+/z×z×z←1+⍳⍵
a:(⍵×⍵+1)÷2
b:(⍵×(1+⍵)×1+2×⍵)÷6
c:(a⍵)*2

10.15 

Use the following expressions to demonstrate why functions si and a of Ex 10.14 are equivalent:

   x←1+⍳5
   x                  ⌽x
   +/x                +/⌽x

   (+/x) + +/⌽x
   x+⌽x
   +/x+⌽x

(See Ex 1.68 for the definition of the reversal function).
 



10.16 

Show that the functions tn:⍵+tn ⍵-1:⍵=0:0 and sn:+/1+⍳⍵ are equivalent.
 

10.17 

Repeat Ex 10.1 for the following functions applied to positive scalar integers:

i) gcd:(⍺|⍵) gcd ⍺:⍺=0:⍵
ii) red:(⍺,⍵)÷⍺ gcd ⍵
iii) test:(⍺÷z)gcd ⍵÷z←⍺gcd⍵
iv) lcm:(⍺×⍵)÷⍺ gcd ⍵
 
10.18 

Repeat Ex 10.1 for the following functions applied to non-negative scalar integers:

i) bin:(z,0)+0,z←bin⍵-1:⍵=0:1
ii) sum:+/bin ⍵
iii) p:+/(bin⍺)×⍵*⍳⍺+1
iv) q:2*⍵
v) r:(⍵+1)*⍺
 
10.19 

a) For each function f of Ex 10.17, define a monadic function fv which, when applied to a two-element vector argument, is equivalent to f . For example, redv v must equal v[0] red v[1] 

b) For various values of a two-element argument a evaluate redv a and compare the values of ÷/a and ÷/redv a .

c) Discuss the statement: The function redv reduces a fraction to lowest form.
 

10.20 

The expression fib n yields a vector of the first n Fibonacci numbers if fib is defined as follows:

fib:z,+/¯2↑z←fib⍵-1:⍵=1:1

a) Show that fib 10 yields the vector: 1 1 2 3 5 8 13 21 34 55

b) Give an informal statement of the rule for generating Fibonacci numbers.

c) The function pr:(1↓⍵)÷¯1↓⍵ yields the pairwise ratio of successive elements of its vector argument. Evaluate pr fib 10 .

d) The ratio determined in part c appear to be approaching a limiting value; this value is called the golden mean, and is given by the expression .5×1+5*.5 . Compare the golden mean with the ratio of a few Fibonacci numbers.
 

10.21 

The signum function defined by sg:(⍵>0)-⍵<0 is a monadic function also denoted by × ; it yields ¯1 or 0 or 1 according to whether the argument is negative, zero, or positive. Discuss the following statements and illustrate them for the case where f:⍵*2 and n←5 :

a) The equation n=f ⍵ has a root in the interval a[0] to a[1] if a s n has the value 1 , where s:1≠×/×⍵-f ⍺ .

b) The function m:.5×+/⍺ yields the midpoint of any interval to which it is applied.

c) If a s n has the value 1 , then either (a[0],m a)s n is 1 , and therefore n=f ⍵ has a root in one of the narrower intervals a[0],m a or a[1],m a .

d) If a s n equals 1 , then the equation n=f ⍵ has a root in one of the narrower intervals a ni n , where:

      ni:⍺[(⍺[1],m⍺)s ⍵],m⍺

10.22 

The root-finder function rf is based on the results of Ex 10.21 and is designed to yield a root of the equation n=f x in the interval from a[0] to a[1] , that is, if x←a rf n , then f x is (approximately) equal to n , the tolerance in the approximation being determined by the tolerance function t :

rf:(⍺ni⍵)rf⍵:t⍵-f m⍺:m⍺
t:1e¯8≥|⍵

a) If f:⍵*2 , show that 1≠×/×12.25-f 2 4

b) Show that 2 4 rf 12.25 yields 3.5 , and verify that f 2 4 rf 12.25 equals 12.25 .

c) Evaluate 1 2 rf 2 and check the result by applying f to it.

d) Redefining the function f as f:+/3.75+(¯4.25×⍵)+⍵*2 , evaluate 1 2 rf 0 .

e) Show that f 1 2 rf 0 is 0 .

f) Evaluate 2 4 rf 0 .
 

10.23 

All possible divisors of an integer k are included in the vector 1+⍳k .

a) For d:0=(1+⍳⍵)|⍵ , evaluate the expression d k for various values of k , and state clearly how the result identifies the actual divisors of k amongst the elements of 1+⍳k .

b) The function f selects from its right argument those elements identified by 1’s in its left argument, in the manner suggested by part a:

f:((1↑⍺)↑⍵),(1↓⍺)f 1↓⍵:0=n⍵:⍳0
n:+/⍵=⍵

Show that 0 1 1 0 1 1 f 1+⍳6 yields 2 3 5 6 .

c) State the effect of the function divs:(d⍵)f 1+⍳⍵ .

d) Show that k÷divs k is equivalent to ⌽ divs k .

e) k is called a perfect number if k=+/¯1↓divs k . Show that 6 and 28 are perfect numbers, and state in words the definition of a perfect number.
 



10.24 

Use the function plus , minus , and times of Section 10.3 to evaluate the expression c plus d and c minus d and c times d for the following pairs of c and d :

c             d
1 2 1 1 3 3 1
1 1 1 2 1
1 1 1 ¯1 1 ¯1 1
 


10.25 

Use the function into and linto of Section 10.3 to evaluate the expression a into b and a linto b . Check the results by computing the corresponding remainder:

  a           b
1 3 3 1 1 5 10 10 5 1
1 3 2 2 4 1 5 7
2 1 3 2 4 1 5 7
 
10.26 

Let v←20↑1 . Then evaluate and compare the two expressions in each part:

a) 1 ¯1 into v
   +\v

b) 1 ¯2 1 into v
   +\+\v

c) 1 ¯3 3 ¯1 into v
   +\+\+\v
10.27  Use the functions pvra and p of Section 10.3 to show complete interpretations of the expressions 1 3 3 1 pvra 2 5 and 1 3 3 1 p 2 5 , making clear why the evaluation of the latter cannot be completed.
 
10.28  Redo part d of Ex 10.22 with f:3.75 ¯4.25 1 pvra ⍵ .
 


10.29  Evaluate the following:
   a←'abcdefghijklmnopqrstuvwxyz '
   b←'coffee'
   d←'0123456789'
   n←'1776'
   a[2 0 1]
   a[8 26 18 8 13 6 26 14 5]
   j←2 14 5 5 4 4
   a[j]
   b=a[j]
   ⌊/b=a[j]
   d[1 7 7 6]
   ⍎n
   ⍎d[1 9 7 6]

10.30  Using the variables specified in Ex 10.29, evaluate:
a) d∘.=n
b) +/d∘.=n
c) a∘.=b
d) +/a∘.=b
e) an←a,d
f) +/an∘.='224 East 25th St'

10.31 

Using the results of Ex 10.30, comment on the following statements:

a) The function cl:+/a∘.=⍵ gives counts of the letters and spaces in its argument.

b) The function cd:+/d∘.=⍵ gives counts of the digits in its argument.
 

10.32 

Using the results of Exercise 10.29 it is clear that the function f:a[⍵] yields b when applied to j .

a) Show that the function if:+/⌊\⍵∘.≠a is inverse to f ; in particular, show that if b yields j .

b) Show that the function ig:+/⌊\⍵∘.≠d is inverse to the function g:d[⍵] ; in particular, show that ig '1776' yields the vector 1 7 7 6 .

c) Compare the function v:+/(ig⍵)×10*⌽⍳+/⍵=⍵ with the execute function ; in particular, show that v '1776' equals ⍎'1776' .
 



10.33  a) Show that the following:
   h←'z←x q y  '
   i←'z←x×y+x-2'
   m←2 9⍴h,i
   ⎕fx m

fix the function q:⍺×⍵+⍺-2 .

b) Show that 3 q 4 yields 15 .
 
10.34  Recalling that the quote character itself is represented by a pair of adjacent quotes, show that the expressions:
   h←'z←cd y              '
   i←'z←+/''0123456789''∘.=y'
   m←2 20⍴h,i
   ⎕fx m
fixes the function cd of Ex 10.31b.
 
10.35  Write expressions to establish each of the functions cl , f , if , g , ig , and v of Exs 10.31-32.
 


10.36  Show that the expression:
⎕fx 'z←x q y' on9 'z←x×y+x-2'
fixes the function q of Ex 10.33.
 
10.37  Write expressions using the function on9 to establish each of the functions cl , cd , f , if , g , ig , and v of Exs 10.31-32.
 


10.38  a) Evaluate:
'q' can9 'x×y+x-2'

and show that it yields a representation of the function q of Ex 10.33.

b) Show that the expression:
⎕fx 'q' can9 'x×y+x-2'

fixes the definition of the function q of Ex 10.33.
 

10.39  Repeat Ex 10.37 using the function can9 instead of on9 .
 


10.40  Repeat Ex 10.37 using the function is9 instead of on9 .
 


10.41  Assuming that:
a←'minus:x-y'
b←'ab:cde:fghi'
evaluate the following:
a) p9 a
b) s9 a
c) p9 b
d) s9 b
e) p9 s9 b
f) s9 s9 b

10.42  Repeat Ex 10.37 using the function sdef9 instead of on9 .
 


10.43  Carry out the detailed steps in the execution of the expression:
  rdef9 'f:y×f y-1:y=0:1'
to show that it establishes the definition of f as the factorial function.
 


10.44  Carry out the detailed steps in the establishment of the functions g and f by the following expressions:
a) adef9 'g:x÷y'
b) adef9 'f:y×f y-1:y=0:1'
(Use the results of Ex 10.43.)
 


10.45  Evaluate the following:
'+ and ' in9 'May+June+July'
'Mmay ' in9 '+ and ' in9 'M3+M14'

10.46  Using the definition:
adef9 'sub9:i9 in9 j9 in9 sw9 y'
for the function sub9  state the result or effect of each of the following expressions:
a) sub9 'p:+/⍺×⍵*⍳+/⍺=⍺'
b) adef9 'p:+/⍺×⍵*⍳+/⍺=⍺'
c) adef9 'f:⍵×f ⍵-1:⍵=0:1'



10.47  Show examples of the use of the function established by:
      def
sqrt:⍵*.5
      def
hyp:sqrt(⍺*2)+⍵*2


10.48 

The remaining exercises develop modifications to the function def which localize names which precede a specification arrow as specified in Sec. 10.1. In the canonical representation, names are localized by adding them to the first row, each preceded by a semicolon. For example, if f is defined by:

      def
f:⍺+z×z←ab+ab←⍵*2

then its canonical representation is:

z9←x9 f y9;z;ab
z9←x9+z×z←ab+ab←y9*2

In what follows assume that the semicolon sc , the empty vector ev , and the alphabet a are specified as follows.

    sc←';'
    ev←''
    a←'abcdefghijklmnopqrstuvwxyz'

Consider the functions fixed by each of the following individual responses to the function def :

bsa:(+/⌊\⍵≠'←')↑⍵
asa:(1++/⌊\⍵≠'←')↓⍵
fn:(+/⌊\⌈/⍵∘.=A)↑⍵
ln:⌽fn⌽⍵
n:sc,z:0=+/z=z←ln bsa ⍵:ev
nl:(n⍵),nl z:0=+/z=z←asa⍵:ev

Examine the behaviour of these functions by applying them to one or more arguments, including arg specified as:

arg←'f:⍺+z×z←ab+ab←⍵*2'

For each function state its behaviour in words, and choose an appropriate name for it. For example: bsa might be called “before the specification arrow”.
 

10.49  Modify the function can9 so as to append the first row of the matrix it produces the list of local names produced by the function nl of Ex 10.48. Verify that this modification causes the function def to localize the names as desired.
 


Originally appeared in the Elementary Functions, IBM Corp., 1974, Chapter 10, then in Elementary Analysis, APL Press, 1976, Chapter 10.

created:  2010-07-31 16:15
updated:2012-08-27 23:10