Help / JforC / Loopless Code II: Adverbs / and ~
>> << Pri JfC LJ Phr Dic Voc !: Rel NuVoc wd Help J for C Programmers
9. Loopless Code II: Adverbs / and ~
The monad +/, which sums the items of its operand, is a special case of the use of the adverb / . It is time to learn about adverbs, and other uses of this one.
Modifiers
An adverb is a modifier. It appears to the right of a noun or verb; the prototype is u a where u is the noun or verb and a is the adverb. The compound u a is a new entity, and not necessarily the same part of speech as u . When the compound u a is executed, it performs the function given by the definition of a and has access to u during its execution. If u a is a verb, then it also has access to the operands of the verb during its execution; the verb u a will then be invoked as u a y if monadic or x u a y if dyadic.
You will note that I didn't have to write x (u a) y . While J gives all verbs equal precedence and executes them right-to-left, it does give modifiers (adverbs and conjunctions) higher precedence than verbs, in the same way that C and standard mathematical notation give multiplication precedence over addition. We will discuss the parsing rules in detail later; for now, know that modifiers are bound to their operands before verbs are executed, and that if the left operand of a modifier has a conjunction to its left (e. g. x c y a), the conjunction is bound to its own arguments first, and the result of that becomes the left argument to the modifier: x c y a is (x c y) a, not x c (y a) . In other words, modifiers associate left-to-right. So, +"1/ (in which " is a conjunction and / is an adverb) is the same as (+"1)/, not +"(1/) . The phrase | +/"1 (4) + i. 3 3 is executed as | ((+/"1) ((4) + (i. 3 3))), in accordance with the rule: right-to-left among verbs, but applying modifiers first. Note that I had to put parentheses around the 4, because "1 4 would have been interpreted as rank 1 4 : collecting adjacent numbers into a list is done before anything is executed.
J includes a rich set of modifiers and even allows you to write your own, though many J programmers will never write a modifier.
What 'Monadic' and 'Dyadic' Mean For Modifiers
An adverb, for example / which we will be studying next, is applied to its left operand. So, if that operand is the verb u, the combination is u/ .
This pair u/ defines a verb, and that compound, like all verbs, has monadic and dyadic versions. When we say 'monad /' or 'monad u/' we are referring to instances of u/ y; when we say 'dyad /' or 'dyad u/' we are referring to instances of x u/ y .
The definition of the adverb defines both valences. As with verbs, the monadic and dyadic cases are independently defined.
Any adverb is allowed to inspect its left operand before deciding what derived verb to create. Many of J's primitive adverbs produce different derived verbs depending on whether the operand is a noun or a verb. When the operand is a noun, we refer to it as m to distinguish it from a verb operand u . The derived verbs for noun and verb operands may be completely different, and for each the two valences can be independently defined. So, the simple case of x/ has four possible derived verbs, depending first on whether x is a noun or a verb and then on whether x/ is used as a monad or a dyad.
It sounds like a lot to remember but as usual the important thing is to know where to look something up when you need a function.
Conjunctions are just like adverbs except that they take two operands, so there are four combinations of noun/verb operands for a conjunction c (u c v, m c v, u c n, and m c n), each of which has monadic and dyadic valences.
The Adverb Monad u/ (Insert)
Monad u/ inserts u between items of y . Monad u/ has infinite rank. As a simple example, +/ 1 2 3 is equivalent to 1 + 2 + 3 :
+/ 1 2 3 6
As usual, we can use fndisplay to explain what's happening:
defverbs 'plus"0' plus/ 1 2 3 +---------------+ |1 plus 2 plus 3| +---------------+
The great power of the adverb concept is that u can be any verb; it's not restricted to +, -, or any other subset of verbs (it can even be a user-written verb). What would monad >./ mean? Well, >./ 1 2 3 would be equivalent to 1 >. 2 >. 3; since each >. picks the larger operand, the result is going to be the largest number; so monad >./ means 'maximum':
>./ 3 1 4 1 5 9 9
and of course 'minimum' is similar:
<./ 3 1 4 1 5 9 1
What about monad ,/? Convince yourself that it combines the first two axes of its operand:
,/ i. 2 3 0 1 2 3 4 5 defverbs 'comma' comma/ i. 2 3 +-------------------+ |(0 1 2) comma 3 4 5| +-------------------+ i. 2 3 4 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $ ,/ i. 2 3 4 6 4 ,/ i. 2 3 4 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
How many atoms are in y? Why, */ $ y :
*/ $ i. 2 3 4 24
We can verify that the rows and columns of the following magic square sum to the same value:
+/ 3 3 $ 8 1 6 3 5 7 4 9 2 15 15 15 +/"1 (3 3) $ 8 1 6 3 5 7 4 9 2 15 15 15
As this last example shows, the items can be of any shape. Applying +/ to the rank-2 array added up 1-cells, while applying +/"1 added up the 0-cells within each 1-cell.
Have you wondered what would happen if there is no item or only 1 item? Good on you if you did. The answer is: if there is only 1 item, the result is just that cell; if there is no cell, the result is a cell of identity elements. The identity element i (also called the neutral) for a dyadic verb v is that value of i such that i v y and y v i are y for any choice of y in the domain of v . For example, the identity element for + is 0, because 0 + y is always y . The identity element for * is 1, and for <. is _ . If there is no identity element for a verb v (for example, $ has no identity element), you will get a domain error if you apply v/ to an empty list. Examples:
+/ 0$0 0 */ 0$0 1
Empty list; result is the identity element.
+/ 1 3 $ 3 5 7 3 5 7
There is a single 1-cell, so the result is that cell. This result has shape 3, not 1 3 . In general, if y has only one item, u/ y produces {.y regardless of what u is.
+/ 0 3 $ 0 0 0 0
There are no 1-cells, so the result is a cell of identity elements. Note that even though there are no cells, the cell still has a shape which is made visible by +/ .
$/ 0$0 |domain error | $/0$0
There is no identity element for $ .
If you don't want to figure out what the identity element for a verb v is you can ask the interpreter by typing v/ 0$0 .
Before moving on you should note that since v/ 1 2 3 is equivalent to 1 v 2 v 3, evaluation starts at the end of the list and moves toward the beginning: so 2 v 3 is evaluated first.
The adverb ~
~ is an adverb. Like all adverbs, it has a monadic and dyadic form. The dyadic form x u~ y is equivalent to y u x; in other words, the operands of u are reversed. The ranks of dyad u~ are the same as those of dyad u, but with left and right rank interchanged. For advanced J dyad ~ is indispensable; even in ordinary use it can save typing and obviate the need for parentheses:
(10 + 2) % 3 4 3 %~ 10 + 2 4
Using %~ to mean 'y divided by x', we can have right-to-left execution without parentheses.
-~/ 2 4 2
When we know y contains exactly 2 items, -/ y is a convenient shorthand to subtract the second from the first without having to write ({.y) - ({:y) . To subtract the first from the second, we simply invert the order of subtraction with -~ .
You can use ~ to create mnemonics. If you have trouble remembering that the arguments to dyad e. are reversed from those to dyad i., you can write
contains =: e.~
and then
'abcdef' contains 'ax' 1 0
Or, if you want to be able to write
7 mod 2 1
as in mathematics, you can get that with
mod =: |~
The monadic form u~ y has infinite rank and is equivalent to y u y, i. e. it applies dyad u with both the left and the right operands equal to the one operand of monad u~ . As with dyad u~, most uses of monad u~ are esoteric, but we know one already: we can sort y into ascending order with either y /: y or our new equivalent /:~ y :
/:~ 3 1 4 1 5 9 1 1 3 4 5 9
>> << Pri JfC LJ Phr Dic Voc !: Rel NuVoc wd Help J for C Programmers