Vocabulary/hook

From J Wiki
Jump to: navigation, search

>> <<   Back to: Vocabulary Thru to: Dictionary

[x] (u v) y Hook Invisible Conjunction

Rank Infinity -- operates on [x and] y as a whole -- WHY IS THIS IMPORTANT?



Two adjacent verbs when not followed by a noun (as in [x] (u v) y) create a hook that executes v followed by u:

We are talking here about after modifiers have been applied, so that there are only verbs and nouns. ({.~ 2&{) is a hook made from the two verbs {.~ and 2&{ .

x (u v) y ⇔ x u v y       result
(u v) y ⇔ y u v y            |
                              u
                             / \
                       x or y   v
                                |
                                y

There is a huge difference between

   i. # 3 1 4 1 5 9
0 1 2 3 4 5

and

   (i. #) 3 1 4 1 5 9  NB. same as 3 1 4 1 5 9  i.  #  3 1 4 1 5 9
6

The first is simply right-to-left execution of # 3 1 4 1 5 9 followed by i. 6 . The second creates a hook out of the verbs (- +:) and then executes that according to the definition above.


A Beginner's Error

When you find two verbs that perform a function you like, like i. and # in the first example above which creates a list of ascending numbers the same length as y, you might try to make a single verb out of them, with

   numberforeach =: i. #   NB. create a list of numbers with length #y

but you will be disappointed when you use it:

   numberforeach 3 1 4 1 5 9
6

The assignment to the name numberforeach created a hook, because the two adjacent verbs were not followed by a noun.

One way to think of this is that when substituting for a name, like numberforeach here, you must put parentheses around the substitution to avoid strange effects. This is akin to ordinary mathematics, where if you know that y=x+2 and you want to substitute that into z=y^2^+2y+5, you use parentheses to get z=(x+2)^2^+2(x+2)+5. In the sentence

   numberforeach 3 1 4 1 5 9

when you substitute for the name, you end up with

   (i. #) 3 1 4 1 5 9

which is a hook and not at all what you wanted.

To do what you wanted you should have written numberforeach =: i.@:#

The substitution model described above is not at all how J actually executes sentences, but it will get you the right answers.


Common uses

1. To fetch the letters of y before the first '$'

   ({.~ i.&'$') 'abc$defg'
abc
   'abc$defg' {.~ i.&'$' 'abc$defg'  NB. Same thing without the hook
abc

2. To reshape y to exactly the shape of x

   2 2 3 ($ ,) i. 2 4
0 1 2
3 4 5

6 7 0
1 2 3
   2 2 3 $ , i. 2 4
0 1 2
3 4 5

6 7 0
1 2 3

More Information

1. When a hook appears in a tacit definition, where it is creating a verb (and therefore not being executed on a noun), it doesn't have to be enclosed in parentheses:

   fetchdollar =: {.~   i.&'$'
   fetchdollar 'first$string'
first

2. In a normal sentence that is executing on noun arguments to produce a noun result, a hook must be enclosed in parentheses

   (#: i.@(*/)) 3 2   NB. hook: odometer function
0 0
0 1
1 0
1 1
2 0
2 1
   #: i.@(*/) 3 2   NB. no hook, just right-to-left execution
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1

3. When there are an even number of verbs in a row, the leftmost one will be the u side of a hook, with the v side coming from the other verbs, interpreted as forks. See the discussion of forks for details.

   ({.~   3 <. #) 1 2 3 4 5  NB. Take up to 3 items of y
1 2 3
   ({.~   3 <. #) 1 2
1 2

Related Primitives

Fork (f g h), Atop (u@v), At (u@:v), Compose (u&v), Appose (u&:v), Under (u&.v), Under (u&.:v)