J-ottings 27: Obverse to Adverse :.:: a Trip along the Brailleway
Vector 17:3, page 40
Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 40
Welcome to the Vector Value excursion from Obverse Central to Adverse! Don’t forget you need an inverse for the return journey – personalised if you like – and note that the inverse is also mandatory (a) when the train gets under (&.) way and (b) when it powers (^:) up with a negative argument. For many primitive monadic verbs and a few dyadic ones an inverse function is well defined, and there’s a list of these on a billboard further down the line. For example log and power are inverse operations, and this underlies the use of &. and ^: in the following examples :
log=.^.
2+&.log 3 NB. e to the power ln2 + ln 3
6
2 ^.^:(_1)3 NB. 2 inverse-log (that is, to the power) 3
8
2 ^.^:(_2)3 NB. 2 inv-log inv-log (i.e. to the power twice) 3
256
The first of these examples performs a transformation, "log to base e", on both arguments prior to the primary operation plus, then performs the "inverse log" transformation on the result. In the second and third examples parentheses are necessary to separate the arguments of the adverb ^: and the adverbially modified verb ^..
Suppose that through some perversity you decided to conclude the log operation by squaring rather than taking anti-logs :
It is hard to see the circumstances in which this would be a sensible thing to do; however when you define your own verbs, J may not be able to define an inverse, and so you are given the opportunity to define your own through obverse. The obverse does not need to have a direct connection with the primary verb, nor does it affect its operation, other than in the contexts of under and negative power. For example suppose you have a primary operation which joins names which are to have trailing blanks deleted prior to the join, with a final comma to be added after the join :
dtb=:({.~i.&' ') :. (,&',') NB. delete trailing blanks with obverse
(dtb 'mickey '),'*' NB. obverse does not affect normal use
mickey*
'mickey ' ,&.dtb 'rooney '
mickeyrooney,
In ordinary usage the obverse side of a coin means the side commonly turned towards you, which in turn usually means "heads" as opposed to "tails". This reflects quite well the idea of obverse in J, because it emphasises (a) that when you use it you are thinking of a verb as a two-sided object, and (b) as with a coin there is no reason why the designs on the two sides should be directly related, although often the relationship is inverse in nature. Another example involves a frequency table verb frtab :
A natural inverse operation would be to "unwrap" the frequencies back to the original data which is what the verb convert=.# i.@# does. So redefine
The conductor will now give a further demonstration of obverse by converting between percentages and multiples as in, e.g. handling compound interest calculations. Suppose the percentage growth rates of an investment are known for a number of years, and it is desired to compute the average overall growth rate throughout the entire period. The following two verbs convert percentages to and from multiples:
petom=:>:@(*&0.01) NB. %age to multiple, e.g. 5 becomes 1.05
mutop=:%&0.01@<: NB. multiple to %age, e.g. 1.05 becomes 5
*/petom 5 6 13 _12 0
1.10677
Now suppose that this result should be given as percentage :
To compute the average, as opposed to total, growth over the period introduce under :
It is reasonable to retain the name petom for the "obverse-enriched" verb since adding the "flip side" verb mutop does not affect its previous function; it is only in the presence of under and negative power that the enrichment occurs. In this case the obverse is just the inverse, which J is smart enough to figure out for itself, since it has a rule that the inverse of a verb u@v is (v^:_1)@(u^:_1), assuming of course that u and v are among the list of primitive verbs for which inverses can reasonably be computed, as is the case with petom. So why bother to write an obverse when all those bright J folks have already given you what you probably wanted anyway, and moreover have provided a conjunction b. which by joining a verb to _1 returns its obverse :
petom=:>:@(*&0.01) NB. back to the original petom
petom b. _1 NB. compute the obverse ..
%&0.01@<: NB. .. which is identical to mutop.
Well, let’s suppose that on the flip side (converting multiples back to percentages) you decide to display an explicit percent sign. Easy, just do
mut=.,&'%'@(":@mutop) NB. enrich mutop with %
mut 1.05
5%
petom=.>:@(*&0.01) :.mut NB. redefine obverse of petom
gm&.petom 5 6 13 _12 0
2.04959%
The verb petom provides a salutary lesson in the power of parentheses. The verb
means (>:@*)&0.01 and is indistinguishable from petom when used directly. However in inverse mode, and bearing in mind that conjunctions have long left scope, the rule for the inverse of petom is
that is (%&0.01 ^:_1)@(<:), or in plain English subtract one and multiply by 100 (that is, divide by 0.01), which is exactly what mutop does. The computed obverse of pet, however, is a somewhat complicated verb, which in the case of a scalar argument reduces to division by 1.01. The programming lesson is that whereas parentheses may be redundant in the normal operation of a verb, they can sometimes have a profound effect on its obverse.
Kirk Iverson recently provided on the J Forum a dazzling example of the use of obverse. The problem is to segregate a vector of integers, say 4 2 2 4 1 4 8, into boxes with empty boxes for those integers in sequence not present. Boxing like items is achieved by using the vector itself as a key (/.)
Now augment the vector with say i.10 :
and finally add an obverse which beheads under box so that the artificially added i.10 is wiped out item by item each from its own box :
Finally do the initial box by key under aug which achieves both numerical ordering and also empty boxes where appropriate :
Previous paragraphs raise the question of which verbs have "reasonable" inverses, to which the answer is – quite a lot. First there are self-inverse monadic verbs for which an even number of applications amounts to "do nothing". These are
- arithmetic
+ - -.(not)% %.(matrix divide)- structural
|.(reverse)|:(transpose)/:(grade up)[ ]andC.(see J-ottings 24)
Next here is a set of monadic verbs which have inverse partners, that is for each of these verbs v^:_1 is equivalent to its partner :
- arithmetic
<:and>:(increment /decrement)
+:or+~and-:(double/halve)
*:or*~and%:(square/square root)
^and^.(power/log)
#.and#:(base/anti-base = decode/encode in APL)
o.and%&(o.1)(multiply by o / divide by o )
j.and%&0j1(multiply by j / divide by j)
+.andj./(vector from/to complex no.)- structural
<and>(box and open)
;~and>@{.(self-raze, i.e. box then duplicate/head and open)
\:and/:@|.(grade down/gradeup following reverse)
,:and{.(itemise/head)
".and":(do and format)
There are also families of monadic verb pairs formed by "currying" dyadic verbs with a noun:
+&nand-&n(add/subtract constant)
*&nand%&n(multiply by/divide by constant)
n&^andn&^.(power of n/log to base n)
n&o.and_n&o.(for appropriate n, e.g. sin and arcsin)
n&|.and_n&|.(shift n left/ shift n right)
p&|:and(ip&|:)(ip = inverse permutation applied to transpose)
The generic property of the inverse i of a monadic verb v is that (i@v) is equivalent to ] .
The "scans" of five arithmetic verbs, namely + * % = and ~: can be reversed by ^:_1, that is each of these verbs has the property that v/\^:_1 is equivalent to ] .
Dyadic verbs have potentially two kinds of inverse, left and right. For example the dyadic + has a right inverse function - because a+b-b = a, that is subtraction on the right "cancels out" addition. However dyadic + has no left inverse because there is no function i for which a i a+b = b for all a and b. By the same reasoning minus has a left inverse minus and a right inverse plus. Inverses for dyadic verbs are rarer than for monadics.
The following is a list of them :
+ |
- |
* |
% |
^ |
^. |
= |
~: |
|
|---|---|---|---|---|---|---|---|---|
| Left inverse | - |
% |
^. |
^ |
= |
~: |
||
| Right inverse | - |
* |
= |
~: |
A left inverse i is characterised by the fact that the fork [iv is equivalent to ] and a right inverse by iv] being equivalent to [ .
"Adverse", like "obverse", is used to define a two-sided verb, but now it provides an alternative verb, the one you use in adversity, when the first one fails. It is unlikely to be an inverse, (although in principle it could be!) If the first verb fails, then the adverse takes over. Here, for example, is a protection device against "index error"
One obvious circumstance in which you might think this could be applied is
to prevent attempted division by zero but this doesn’t work because division by 0 is not an error in J - the result is infinity ( _ ). The only circumstance in which 0 would be delivered is on an attempt to divide characters, or two vectors of unequal lengths, both greater than 1.
Since they connect verbs, "obverse" and "adverse" are conjunctions, but unlike the more commonly used conjunctions they define "flip-sides", rather than creating fundamentally new composite verbs. To summarise, an obverse is a user-defined inverse, adverse is the emergency exit to forestall error conditions.
And to get things back on the rails, there’s a regulator too – if you didn’t like the ride, just have a word with the driver’s son!