Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Rich H.J for C programmers.2006.pdf
Скачиваний:
18
Добавлен:
23.08.2013
Размер:
1.79 Mб
Скачать

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. We will begin our study of modifiers with the adverb monad u/ which goes by the mnemonic 'Insert'.

The Adverb Monad u/

Monad u/ (by which we mean / with a verb left operand, used as u/ y rather than as x u/ y which is dyad u/ and is completely different; note that m/ y where m is a noun is different yet), 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:

66

 

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:

 

2 3

 

 

 

 

 

 

0

1

,/ i.

4

 

 

 

 

 

 

2 3

5

 

 

 

 

 

 

 

 

defverbs 'comma'

 

 

 

 

+

 

comma/ i. 2 3

+

 

 

 

 

 

 

 

comma

 

 

 

 

 

|(0 1 2)

 

3 4 5|

 

 

 

 

+-------------------

 

i. 2 3 4 0

1

+

3 4

5

6

7

8

 

2

 

9 10

 

11

 

 

 

 

 

 

12 13 14 15

16 17 18 19

20 21 22 23

$ ,/ i. 2 3 4

6 4

0

,/ i.

2 3 4

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:

67

+/ 3 3

$ 8 1 6

3 5 7

4 9 2

 

15 15 15

 

$ 8

1 6 3

5 7 4

9 2

+/"1 (3 3)

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 cell or only 1? Good on you if you did. The answer is: if there is only 1 cell, the result is just that cell; if there is no cell, the result is a cell of identity elements. The identity element i for a dyadic verb v is that value of i such that i v y is y for any choice of y . 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 1 1-cell, so the result is that cell. This result has shape 3, not 1 3 .

+/ 0 3 $ 0 0 0 0

There are 0 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

If you don't want to figure out what an identity element for a verb v is you can ask the interpreter by typing v/ 0$0 .

Before we move on you should note that since v/ 1 2 3 is equivalent to

1 v 2 v 3, 2 v 3 is evaluated first: the operation starts at the end of the list and moves toward the beginning.

The adverb ~

~is an adverb. Like all adverbs, it has a monadic and dyadic form. The dyadic form

xu~ 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 time and obviate the need for parentheses:

68

(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 -~ .

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

69