There is another language within J, a microcode for J as it were. Like Moliere's M. Jourdain, who was astonished to find he had been speaking prose for forty years without knowing it, you have been using a small subset of this language unwittingly throughout our investigations. The hidden language describes a way of coding called tacit programming, and it is time for you to learn it in full. J's tacit language is the irreducible essence of a programming language. It describes your algorithm using only the ordering of the J primitives you have already learned. It has a grammar without words, which you use to write programs without visible operands; yet its renouncing these seemingly essential components is self-denial rather than self-mutilation, for it retains the vigor to express any algorithm. It is as evanescent as the breeze and as powerful as the hurricane. It is a sublime creation.
We begin our exploration with this simple program:
The first step toward enlightenment is to realize that something so simple is a program. You may object: But it can't be a program. It has no parameters. It has no name. How would I invoke it? It's a primitive, maybe. Or a verb. Or a typographical error. But not a program.
Let me make the case that it is indeed a program. I say that a bit of text deserves the title of 'program' if it produces a systematic result when executed with suitable arguments. And I say that the program '-' satisfies this definition. Certainly I can supply it with arguments
5 7 - 2
and get the expected result. The program does not refer to its operands explicitly, but as long as we make the agreement that the arguments to a program appear as nouns to its left and right, the program has no doubt about how to find its arguments. Of course, we have been using this convention for verbs all along.
I can give this program a name:
minus =: -
5 7 minus 2
minus can be used in place of - anywhere. When we look at the value of minus, we see what it contains:
9!:3 (5) NB. Do this once to select simplified display
minus is equivalent to - . In J we call it a verb, but it has all the essential features of a program. In fact, minus is two programs, because it can be executed monadically as well:
minus 6 8
The point is that every J verb, even the primitives and the compound verbs, is a program in the usual sense. Verbs like minus, that do not mention their operands by name but instead apply them according to J's parsing rules, are called tacit verbs. Verbs created by m :n, like dyad : '+/ y', that mention their operands by name are called explicit verbs. The compound verbs we have learned already are examples of tacit verbs. Some of the verbs that we have had occasion to define so far can be written in tacit form:
addrow =: monad : '+/ y'"1
could be rewritten as
addrow =: +/"1
v =: dyad : '1.04 * x + y'
is equivalent to
v =: 1.04&*@:+
as we have seen. We have already encountered tacit definitions without noticing:
dotprod =: +/@:*"1
1 2 3 dotprod 1 2 3
and we can certainly define more.
sortup =: /:~
defines a verb that sorts its operand into ascending order:
sortup 31 41 59 26 53
26 31 41 53 59
Some of the verbs we have encountered seem too complex for a compound verb. For example, in
mean =: monad : '(+/ y) % #y'
we need to perform two operations on y and combine their results, something that is beyond the capabilities of the compound verbs we have encountered so far. We will next learn how to produce a tacit equivalent for mean and a great many other verbs.