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

Chapter 11: Tacit Verbs Concluded

In this chapter we consider some general points in writing expressions for tacit verbs.

Here is an example of a tacit verb. It multiplies its argument by 3:

f =: * & 3 f 4
*&3 12

Recall from Chapter 03 that the bonding operator & produces a monad from a dyad by fixing one of the arguments of the dyad. The scheme is that if N is a noun and V a dyadic verb, then:

            (N & V) y    means   N V y
            (V & N) y    means   y V N
We take the bonding operator & as an example of a typical operator, where arguments may be nouns or verbs. In general, N can be an expression denoting an noun, and V an expression denoting a verb. We look now at how these expressions get evaluated. The general rules are set out formally in Appendix 1 but here we take an informal first look at a few of the main points.

11.1 If In Doubt, Parenthesize

Here is another tacit verb. Its general form is V&N. It multiplies its argument by 5%4, that is, by 1.25

scale =: * & (5 % 4) scale 8
*&1.25 10

Are the parentheses around 5 % 4 necessary here? If we omit them, we see:

   SCALE =: * & 5 % 4
so they evidently make a difference. SCALE is a number, not a verb. The result of 1.25 is produced by applying the verb *&5 to the argument % 4 (the reciprocal of 4)

% 4 (* & 5) (% 4) * & 5 % 4
0.25 1.25 1.25

We have a general rule: informally we can say that conjunctions get applied before adjacent verbs. Thus in the expression * & 5 % 4 the first step is to apply the & operator to its arguments * and 5.

Why is the right argument of & just 5 and not 5%4? Because of another general rule: the right argument of a conjunction is as short as possible. We say that a conjunction has a "short right scope". By contrast, we say that a verb has a "long right scope" to express what we earlier called the "rightmost first" rule for verbs.

What about the left argument of an operator? An adverb or conjunction is said to have "long left scope", that is, as much as possible. For example, here is a verb z which adds 3 to the square of its argument. 3 plus the square of 2 is 7.

z =: 3 & + @: *: z 2
3&+@:*: 7

We see that the left argument of @: is the whole of 3&+.

If we are in doubt in any particular case we can always make our intention clear. We can write parentheses around a part of an expression, that is, around a function - verb or operator - together with its intended argument(s). For example, verb z can be written with parentheses as:

z =: (3 & +) @: *: z 2
3&+@:*: 7

Sometimes parentheses are necessary and sometimes not, but, let me emphasize, if in doubt, parenthesize.

11.2 Names of Nouns Are Evaluated

In an expression of the general form N&V or V&N, the the names of any nouns occurring in N are evaluated right away. Here is an example of a function f to multiply by five-fourths. The numerical value is given as a%b where a and b are nouns.

a =: 5 b =: 4 f =: * & (a % b) f 8
5 4 *&1.25 10

We see that function f contains the computed number 1.25 so that a%b has been evaluated.

11.3 Names of Verb Are Not Evaluated

In N&V the verb-expression V is not necessarily fully evaluated. If expression V is the name of a verb, then the name is enough:

w =: * g =: w & (a % b) g 8
* w&1.25 10

11.4 Unknowns are Verbs

When a new name is encountered, it is assumed to be a yet-to-be-defined verb if it possibly can be.

h =: ytbd & (a%b) ytbd =: * h 8
ytbd&1.25 * 10

Any sequence of hitherto-unknown names is assumed to be a train of verbs:

   Ralph Waldo Emerson
Ralph Waldo Emerson
Consequently, a verb can be defined in "top-down" fashion, that is, with detail presented later. For example, here is a Celsius-to-Fahrenheit converter presented top-down.
   ctof =: shift @ scale
           shift =: + & 32
           scale =: * & (9 % 5)        

ctof ctof 0 100
shift@scale 32 212

We can see that ctof is defined solely in terms of (the names) scale and shift. Hence if we now change scale or shift we will effectively change the definition of ctof.

   ctof 100
   scale =: * & 2
   ctof 100
   scale =: * & (9 % 5)
   ctof 100
The possibility of changing the definition of a function simply by changing one of its subordinate functions, may or may not be regarded as desirable. It is useful, in so far as we can correct a definition just by changing a small part. However, it may be a source of error: we may introduce a new verb, scale say, forgetting that scale is already defined as subordinate in ctof.

There are ways to protect ctof against accidental redefinition of its subordinate functions. Firstly, we can put a wrapper of explicit definition around it, making scale and shift local, thus:

   CTOF =: 3 : 0
shift =. + & 32
scale =. * & (9 % 5)
shift @ scale y
   CTOF 100
A second method is to, so to speak, "freezing" or "fixing" the definition of ctof, with the "Fix" adverb f. (letter-f dot). Observe the difference between the values of the verbs ctof and (ctof f.)

ctof ctof f.
shift@scale +&32@(*&1.8)

We see that adverb f. applied to a tacit verb replaces names by definitions, giving an equivalent verb defined only in terms of built-in functions. Here is yet another definition of ctof.

   scale =: * & (9 % 5)
   shift =: + & 32
   ctof  =: (shift @ scale) f.

ctof ctof 0 100
+&32@(*&1.8) 32 212

After this definition, the names scale and shift are still defined, but are no longer important in the definition of ctof.

11.5 Parametric Functions

The following example shows the consequences of nouns being evaluated and verbs not in an expression for a tacit verb.

A curve may be specified by an equation such as, for example:

                y  =  lambda * x * (1 - x)
This equation describes a family of similar parabolic curves, and different members of the family are picked out by choosing different values for the number lambda.

A function to correspond to this equation might be written explicitly as verb P:

   P =: 3 : 'lambda * y * (1-y)'
Here lambda is not an argument to function P, but a variable, a number, which makes a difference to the result. We say that lambda is a parameter, or that function P is parametric.

x=:0.6 lambda=: 3.0 P x lambda=: 3.5 P x
0.6 3 0.72 3.5 0.84

Now, can we write a tacit version of P taking lambda as a parameter?

lambda is currently 3.5. If we now generate a tacit form of P

   tP =: 13 : 'lambda * y * (1-y)'
3.5 * ] * 1 - ]
then we see that lambda is treated as a constant, not a parameter. This is not what we want. We try again, this time ensuring that lambda is not specified beforehand, by erasing it:
   erase <'lambda'
[: lambda [: * ] * 1 - ]
Now we see that tP is a train of verbs, where lambda (being unknown) is assumed to be a verb. This assumption conflicts with the intended meaning of lambda as a number. Hence with lambda as a number, we get an error:

lambda=: 3.5 tP x
3.5 error

Whether or not lambda is specified in advance, it appears that a fully tacit exact equivalent to P is not possible. However we can come close.

One possibility is to compromise on "fully tacit". Here tP is a train of verbs, where the first is explicitly-defined to deliver the value of lambda regardless of its argument.

tP =: (3 : 'lambda') * ] * (1: - ]) tP x
3 : 'lambda' * ] * 1: - ] 0.84

Another possibility is to compromise on "exact equivalent". Here we take parameter lambda to be, not a number, but a constant function (see Chapter 09) which delivers a number.

For example, a value for the parameter could be written as

   lambda =: 3.5 " 0
and tP could be defined as:

tP =: lambda * ] * (1: - ]) tP x
lambda * ] * 1: - ] 0.84

Now we can vary the parameter without redefining the function:

lambda =: 3.75 " 0 tP x
3.75"0 0.9

This is the end of Chapter 11

Table of Contents

The examples in this chapter were executed using J version 701. This chapter last updated 29 Jul 2012
Copyright © Roger Stokes 2012. This material may be freely reproduced, provided that this copyright notice is also reproduced.
