J – Where Have All the Variables Gone?
Vector 12:1, page 30
Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 30
One of the hardest, and most stimulating, things about learning J was (for the author) the challenge of removing any mention of variables in function definitions. The seductive elegance of the definition of the function for the mean as mean =. +/ % # hid the fact that the syntax of the function was clearly presupposed. In defining new functions one had to keep clearly in mind whether component functions were to be used dyadically or monadically. In short, one had to be keenly aware of how the data was to be given to the function and what would happen to it, although this information did not appear in the written functions (but, of course, could be deduced by parsing the statements). There was the continual tendency to see [ and ] as the left and right variables rather than as functions that returned those variables. Even with this fact clear, the penny did not drop. It was in a chat with Ken Iverson during his November ’94 visit to Toowoomba about the naming of a function that (at least one layer of) scales finally fell from my eyes. Ken asked, ‘Well, what is it that the function delivers ?’ Whatever it was, that should be the name of the function. Obviously. But obviously it is something that can be said again even if it has been said before because it seems to be missed so easily.
To demonstrate the importance of this simple principle, let us consider the problem of finding the width, w, of an interval (a,b). Clearly the name of this function should be w, and to define it, one must either decide on the syntax of the function — will it be a w b, or w (a,b), and remember to keep this clearly in mind — or, simply write w =. b - a , where, "obviously", a and b are functions that deliver the values of those variables and the expression for w is a fork. Choosing the latter approach allows one to specify either syntax for w. If w is to be used dyadically, then we define a=. [ and b=. ] whereas if it is to be used monadically, then a=. {. and b=. {: are appropriate definitions. The definition of function w is not affected by the choice of syntax.
Next suppose the interval (a,b) is to be divided into n equal subdivisions each of width, h. The function that delivers the subdivision width should be called, h, and can be defined by h =. (b-a) % n where a,b,n are functions that deliver those variables from the supplied data.
The subdivision points are given by the function
Finally one must decide whether this function will be called as
or as
If we choose the dyadic form then we make the definitions
and find that subdivision_points f. is
If we choose the monadic syntax then we write
and subdivision_points f. is
There may be other preferred ways of delivering the data to the subdivision_points function for which the a,b and n functions would have to be defined appropriately, but the subdivision_points function needs no adjustment. In practice it will be found that a fixed function like
will run six to seven times faster than the original subdivision_points function. (The monadic form is also marginally faster than the dyadic form.)
So where have all the variables gone? Gone to functions every one.
In algebra class, the key to beginning a problem is to say "let x be the number of …" ; in J the key might be to say "let x be the function that goes and gets the number of …". It is probably a more palatable statement for students beginning a study of algebra.