>>  <<  Usr  Pri  JfC  LJ  Phr  Dic  Rel  Voc  !:  Help  Learning J

Chapter 13: Explicit Operators

This chapter covers explicit definition of operators, that is, adverbs and conjunctions defined with the colon conjunction.

The scheme for explicit definition is:

            1 : body     is an adverb
            2 : body     is a conjunction
where body is one or more lines of text. The possibilities for the result produced by an operator so defined are: a tacit verb, an explicit verb, a noun or another operator. We will look at each case in turn.

13.1 Operators Generating Tacit Verbs

Recall from Chapter 07 the built-in rank conjunction ". For any verb u, the expression u"0 is a verb which applies u to the 0-cells (scalars) of its argument.

Now suppose we aim to define an adverb A, to generate a verb according to the scheme: for any verb u

         u A   is to be     u " 0
Adverb A is defined explicitly like this:

A =: 1 : 'u " 0' f =: < A f 1 2
1 : 'u " 0' <"0 +-+-+

In the definition (A =: 1 : 'u " 0') the left argument of the colon is 1, meaning "adverb".

The right argument is the string 'u " 0'. This string has the form of a tacit verb, where u stands for whatever verb will be supplied as argument to the adverb A. In the explicit definition of an adverb, the argument-variable is always u.

Adverbs are so called because, in English grammar, adverbs modify verbs. In J, by contrast, adverbs and conjunctions in general can take nouns or verbs as arguments. In the following example, adverb W is to generate a verb according to the scheme: for integer u

        u W    is to be   < " u
that is, u W boxes the rank-u cells of the argument. The definition of W is shown by:

W =: 1 : '< " u' 0 W z =: 'abc' 0 W z 1 W z
1 : '< " u' <"0 abc +-+-+-+

For another example of an adverb, recall the dyad # where x # y selects items from y according to the bitstring x.

y =: 1 0 2 3 1 0 1 1 # y
1 0 2 3 1 2 3

To select items greater than 0, we can apply the test-verb (>&0)

y >&0 y (>&0 y) # y
1 0 2 3 1 0 1 1 1 2 3

A tacit verb to select items greater than 0 can be written as a fork f:

f =: >&0 # ] f y
>&0 # ] 1 2 3

This fork can be generalised into an adverb, B say, to generate a verb to select items according to whatever verb is supplied in place of the test >&0.

   B =: 1 : 'u # ]'
If we supply >&1 as a test-verb:

g =: (>&1) B y g y
>&1 # ] 1 0 2 3 2 3

We see that the body of B is the fork to be generated, with u standing for the argument-verb to be supplied. Conjunctions, taking two arguments, are defined with (2 : '...'). The left argument is u and the right is v

For example, consider a conjunction THEN, to apply one verb and then apply another to the result, that is, a composition. The scheme we want is:

           u THEN v     is to be v @: u
and the definition of THEN is:

THEN =: 2 : 'v @: u' h =: *: THEN < h 1 2 3
2 : 'v @: u' <@:*: +-----+
|1 4 9|

For another example, consider counting (with #) those items of a list which are greater than 0. A verb to do this might be:

foo =: # @: (>&0 # ]) y foo y
#@:(>&0 # ]) 1 0 2 3 3

We can generalize foo to apply a given verb u to items selected by another given verb v. We define a conjunction C with the scheme

             u C v   is to be   u @: (v # ]) 
and the definition of C is straightforwardly:

C =: 2 : 'u @: (v # ])' f =: # C (>&0) y f y
2 : 'u @: (v # ])' #@:(>&0 # ]) 1 0 2 3 3

13.1.1 Multiline Bodies

The right argument of colon we may call the body of the definition of our operator. In the examples so far, the body was a string, a schematic tacit verb, for example 'v .@: u' . This is the verb to be delivered by our operator. More generally, the body can be several lines. The idea is that, when the operator is applied to its argument, the whole body is executed. That is, each line is evaluated in turn and the result delivered is the value of the last line evaluated. This is exactly analogous to explicit verbs, except that here the result is a value of type "function" rather than of type "array".

Here is an example of a multi-line body, the previous example done in two steps. To apply u to items selected by v, a scheme for conjunction D could be written:

         u D v  is to be  (u @: select) where select is v # ] 
and D defined by
   D =: 2 : 0
select =: v # ]
u @: select
Again counting items greater than 0, we have

f =: # D (>&0) y f y
#@:select 1 0 2 3 3

The first line of D computes an inner function select from the right argument. The second line composes select with the left argument, and this is the result-verb delivered by D.

Now this definition has an undesirable feature: we see that select is defined as a global (with =:). It would be better if select were local.

However, we can see, by looking at the value of the verb f above, that select must be available when we apply f. If select is local to D, it will not be available when needed.

We can in effect make select local by using the "Fix" adverb (f.) (letter-f dot.) The effect of applying "Fix" to a verb is to produce an equivalent verb in which names are replaced by by their corresponding definitions. That is, "Fix" resolves a tacit verb into its primitives. For example:

p =: + q =: * r =: p,q r f.
+ * p , q + , *

Here is how we use Fix to enable select to be local. In the example below, notice that we Fix the result-expression on the last line:

   E =: 2 : 0
select =. v # ]
(u @: select) f.
Now a verb to count greater-than-0 items can be written:

g =: # E (>&0) y g y
#@:(>&0 # ]) 1 0 2 3 3

We see that g, unlike f, has no local names.

13.2 Explicit Operators Generating Explicit Verbs

13.2.1 Adverb Generating Monad

Consider the following explicit monadic verb, e. It selects items greater than 0, by applying the test-verb >&0.

e =: 3 : '(>&0 y) # y' y e y
3 : '(>&0 y) # y' 1 0 2 3 1 2 3

We can generalise e to form an adverb, F say, which selects items according to a supplied test-verb. The scheme we want is: for any verb u:

         u F   is to be    3 : '(u y) # y'
Adverb F is defined by:
   F  =: 1 : '(u y) # y'
Now the verb >&1 F will select items greater than 1:

y >&1 F y
1 0 2 3 2 3

In the body of F the variable u stands for a verb to be supplied as argument to adverb F. If this argument is say >&1, then y stands for an argument to the generated explicit verb 3 : '(>&1 y) # y'.

That is, our method of defining the generated verb is to write out the body of an explicit definition, with u at places where a supplied verb is to be substituted.

13.2.2 Conjunction Generating Monad

A conjunction takes two arguments, called u and v. Here is an example of a conjunction to generate an explicit monad.

As before, we specify the generated verb, by writing out the body of an explicit verb. Here y stands for the argument of the generated verb and u and v stand for argument-verbs to be supplied to the conjunction. In this example the body is multi-line. As before, u will be applied to items selected by v

   G  =: 2 : 0
selected =. (v y) # y
u selected
Now a verb to count greater-than-zero items can be written as # G (>&0):

y # G (>&0) y
1 0 2 3 3

13.2.3 Generating a Dyad

For the next example, let us define a conjunction generating an explicit dyad. Suppose we want a conjunction H such that, schematically, for verbs u and v

         u H v    is to be    4 : '(u x) + (v y)'
Recall from Chapter 12 that there is another way to write an explicit dyad. Beginning with 3 : we can write a multi-line body in which a solo colon separates monadic and dyadic cases. Here we have no monadic case, so the scheme above can be equivalently written as:
         u H v    is to be    3 : 0
                              (u x) + (v y)
The explicit definition of H follows straightforwardly:
   H =: 2 : 0
(u x) + (v y)
We see:

(*: 2) + (%: 16) 2 (*: H %:) 16
8 8

13.2.4 Review

So far, we have seen that for operators introduced with 1 : or 2 :, there are two kinds of definition.

  • The first kind generates a tacit function. The body of the operator is executed (that, is evaluated) to compute the value of the result-function. Notice that the argument-variables occurring in the body are u or v

  • The second kind generates an explicit function. A convenient way to define the generated explicit function is to write out a body for it. Here x and y are arguments to the generated function in the usual way. Additionally, occurrences of u or v in this body are arguments to the operator which will be substituted into the generated body. Such a body, containing argument variables x or y or u or v, is the body of the operator. Thus when arguments are supplied to the operator, the body is not executed, but reproduced (after substituting arguments for u or v) as the body of the generated explicit function.
The J system recognises which kind is intended by determining which of the argument-variables u v x y occur in the the body.

If we have ONLY u or v or both, then the generated function is tacit.

If we have BOTH (u or v) AND (x or y) then the generated function is explicit.

On this basis, the cases we have considered are:

1 : '..  u  ..'          tacit-generating adverb 
2 : '..  u  v ..'        tacit-generating conjunction
1 : '..  u  y ..'        explicit-monad-generating adverb 
1 : '..  u  x  y ..'     explicit-dyad-generating adverb
2 : '..  u  v  y ..'     explicit-monad-generating conjunction
2 : '..  u  v  x  y ..'  explicit-dyad-generating conjunction

13.2.5 Executing the Body (Or Not)

We said above that, for a tacit-function-generating operator, the body is executed (or evaluated) when arguments are supplied. This can be demonstrated.

First, here is a utility verb which displays its argument on-screen.

   display =: (1 !: 2) & 2
Now insert display 'hello' into a tacit-generating operator:
     R =: 2 : 0
display 'hello'
select =. v # ]   
(u @: select) f.
When R is applied to its argument, the body is demonstrably executed:
   f =: # R (>&0)
   f 1 0 2 0 3
By contrast, for an explicit-function-generating operator, when arguments are supplied, the body is not executed, but rather becomes the body of the result function (after substituting the arguments). We can demonstrate this by inserting display 'hello' into the body of the operator, and observing that it becomes part of the result-function.
   S =: 2 : 0
display 'hello'
selected =. (v y) # y  
u selected
we see that the body of S is NOT executed when S is applied to its argument, but it IS executed when the generated verb g is applied.
   g =: # S (>&0)
   g 1 0 2 0 3

13.2.6 Alternative Names for Argument-Variables

The arguments to operators may be nouns or verbs. There is a way of constraining arguments to be nouns only, that is, to cause verbs to be signalled as errors. To impose the constraint, we write an argument-variable as m rather than u, or n rather than v. For example, without the constraint we could write:

P =: 1 : '+ & u' * P 7 P
1 : '+ & u' +&* +&7

With the constraint we write:

Q =: 1 : '+ & m' * Q 7 Q
1 : '+ & m' error +&7

We said above that with ONLY u or v or both occurring as argument variables, we get a tacit verb generated. For the sake of completeness, we should add m and n to this list.

Furthermore, if the only argument variables are x or y or both, we get a tacit verb, not an explicit verb. That is, in the absence of u or v or m or n then x and y are equivalent to u and v.

13.3 Operators Generating Nouns

Operators can generate nouns as well as verbs. Here is an example.

A fixed point of a function f is a value p such that (f p) = p. If we take f to be

   f =: 3 : '2.8 * y * (1-y)'
then we see that 0.642857 is a fixed-point of f
   f 0.642857
Not every function has a fixed point, but if there is one we may be able to find it. We can iterate the function until there is no change (with ^: _ - see Chapter 10), choosing a suitable starting value. A crude fixed-point-finder can be written as an adverb FPF which takes the given function as argument, with 0.5 for a starting value.

FPF =: 1 : '(u ^: _ ) 0.5' p =: f FPF f p
1 : '(u ^: _ ) 0.5' 0.642857 0.642857

13.4 Operators Generating Operators

Here is an example of an adverb generating an adverb.

First note that (as covered in Chapter 15) if we supply one argument to a conjunction we get an adverb. The expression (@: *:) is an adverb which means "composed with square". To illustrate:

CS =: @: *: - CS - CS 2 3 - *: 2 3
@:*: -@:*: _4 _9 _4 _9

Now back to the main example of this section. We aim to define an explicit adverb, K say, which generates an adverb according to the scheme: for a verb u

          u K    is to be     @: u
Adverb K can be defined as below. We see that adverb K delivers as a result adverb L:

K =: 1 : '@: u' L =: *: K - L - L 2 3
1 : '@: u' @:*: -@:*: _4 _9

This is the end of Chapter 13.

Table of Contents

The examples in this chapter were executed using J version j701/beta/2010-11-24/22:45. This chapter last updated 22 Dec 2010
Copyright © Roger Stokes 2010. This material may be freely reproduced, provided that this copyright notice is also reproduced.

>>  <<  Usr  Pri  JfC  LJ  Phr  Dic  Rel  Voc  !:  Help  Learning J