Ch 11: Tacit Verbs Concluded

| # 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`:
`v =: * & 3` | `v 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
       SCALE
    1.25
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
    212
       scale =: * & 2
       ctof 100
    232
       scale =: * & (9 % 5)
       ctof 100
    212
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
    212
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.80000000000000004)
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.80000000000000004)
    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.)'
       tP
    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'
    1
       tP =: 13 : 'lambda * y. * (1-y.)'
       tP
    [: 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

NEXT
Table of Contents
Index

Copyright © Roger Stokes 2004. This material may be freely reproduced, provided that this copyright notice is also reproduced.

last updated 4 Oct 2004