Vocabulary/Verbs

From J Wiki
Jump to navigation Jump to search

Back to: Vocabulary

Verbs

Verbs are programs. Verbs operate on one or two noun operands, and produce a result which is always a noun.

The simplest verbs are the primitives, such as +. Larger verbs are created by connecting other verbs together.


When Is a Verb Executed?

Execution of a sentence proceeds from right to left.

A verb is executed when it has a noun to its right, and does not have a conjunction to its left.

This is a simplified distillation of J's parsing rules, which control the order of execution. Modifiers are executed before verbs, and usually produce verbs. For example,

   2 + *: 3 4 5
11 18 27

First *: 3 4 5 is executed, since *: has a verb to its left, producing 9 16 25; then 2 + 9 16 25 is executed.

   2 & + 1 2 3
3 4 5

+ 1 2 3 is not executed. + has the conjunction & to its left. 2&+ is executed, producing a derived verb, and this derived verb is executed on 1 2 3.


How Is a Verb Executed?

The first question when a verb is executed is: how is it executed? There are two ways:

  • If the verb has a noun to its left, the verb is executed dyadically: the noun to the left and the noun to the right of the verb become the x and y arguments to the verb.
  • If the verb does not have a noun to its left, the verb is executed monadically, and the noun to the right of the verb becomes the y argument.

The type of invocation is called the valence of the invocation: either monadic or dyadic.

Every verb, whether a primitive or a user-defined verb, may be invoked as a monad or dyad. The choice of which kind of invocation is up to the code that invokes the verb.

The definition of the verb contains completely separate definitions to handle the two valences. These definitions are completely unrelated, like multiple personalities that inhabit the same body.

If a verb is invoked using a valence that was omitted in the verb definition, domain error is signaled.


Figuring Out The Valence

Determining the valence of an invocation can be tricky. Because modifiers have execution priority over verbs, it is not sufficient to check whether the word to the left of the verb is a noun. You must look one word farther than that, to see if the word to the left of the noun is modified by a conjunction. Only then can you tell whether the invocation of the verb is monadic or dyadic.

   3 %: 64 729
4 9

The dyad %: was executed, taking the cube root.

   3 + %: 64 729
11 30

The monad %: was executed, taking the square root. Then 3 was added.

   + & 3 %: 64 729
11 30

The 3 is not a left operand to %:! The 3 is taken by the conjunction & to produce the verb +&3, so the sentence is like
(+&3) %: 64 729.
The square root is executed, followed by +&3 which adds 3.


Order of Evaluation

As mentioned above, modifiers are executed before verbs, and modifiers produce verbs.

This is an oversimplification of the parsing rules, but not much of one.

The resulting sequence of verbs is executed right to left with no deviation. All verbs have the same priority.

If the lack of an operator-precedence table seems odd to you, consider that J has about 100 verbs, and that user-written verbs are treated exactly the same as primitives. What would an operator-precedence table look like, and how long would it take to learn it?

You do have to remember that the rules of standard math notation do not apply:

   3 * 4 + 1
15


Verb Rank

For any verb, each valence (monad or dyad) has a rank which specifies the largest k-cell that valence can be applied to:

  • The rank of the monad is a single number
  • The rank of the dyad is two numbers, one for each argument, x and y.

Typically the ranks of both valences are reported together (e.g. by b.0) as a list of 3 atoms:

  • Atom 0 - the monad rank (i.e. of the y-argument)
  • Atom 1 - the left dyad rank (i.e. of the x-argument)
  • Atom 2 - the right dyad rank (i.e. of the y-argument).

For example, if the verb rank of the monad v is k, J computes (v y) as follows:

1. splits y into several k-cells 2. applies the verb v to each k-cell in turn 3. assembles the results for all k-cells into a single array result by use of the frame of y.

If the rank of the argument is less than or equal to the verb rank k, the verb is applied to the entire argument.

It follows that to specify a verb rank of Infinity (_) guarantees that the corresponding k-cell is the entire argument (x or y), however large its rank happens to be.


The Value of a Verb

The value of a verb is the code needed to recreate the verb.

To see the value of a verb, type its name into the J session as a sentence by itself:

   NB. display the definition of verb: jhostpath_j_
   jhostpath_j_
'\'&(I.@(e.&'/\')@]})

Remember:

  • to execute a verb monadically you must have a noun to the right of it, i.e. you must give it a y-argument
  • to execute a verb dyadically you must give it both an x-argument and a y-argument.


Creating A Verb

Create a verb in one of two ways:

  • An anonymous verb is created when a modifier is executed.
  • A named verb is created when a verb value is assigned to a name.

It is not necessary to name a verb. You can create an anonymous verb, execute it right away, and discard it.

   2&+             NB. create an anonymous verb. J returns the verb's value, which it displays
2&+
   2&+ 3 4 5       NB. create an anonymous verb and execute it
5 6 7
   plustwo =: 2&+  NB. create a verb, then save it as a named verb
   plustwo 3 4 5   NB. execute the named verb
5 6 7
   plustwo         NB. For the named verb, show its value (--a verb)
2&+


Explicit Definition

The (:) modifier, in its special 3 : 0 and 4 : 0 forms, creates an explicitly defined anonymous verb. The 0 part tells the interpreter to stop executing input and instead read lines until a line containing just a right parenthesis:

)

The lines between the : 0 line and the ) delimiter are the body of the anonymous verb. They are saved away as part of the anonymous verb. When the verb is executed, the lines of the body are executed, one by one.

The 4 : 0 form creates a verb that has only a dyadic valence. The 3 : 0 form creates a verb that has a monadic valence; in addition, if the body contains a line containing just a colon:

:

the lines of the body before the colon are the body of the monadic valence, and the lines after the colon are the body of the dyadic valence.

Normally you will assign the anonymous verb created by : to a name so it doesn't disappear.

   mverb =: 3 : 0  NB. monad only
echo 'mverb executed!'
)
   dverb =: 4 : 0  NB. dyad only
echo 'dverb executed!'
)
   bverb =: 3 : 0  NB. Dual-valence, i. e. both valences
echo 'monadic bverb executed!'
0 bverb 0
:
echo 'dyadic bverb executed!'
)
   mverb ''
mverb executed!
   0 dverb ''
dverb executed!
   dverb ''   NB. dverb has no monadic valence
|domain error: dverb
|       dverb''
   bverb 0
monadic bverb executed!
dyadic bverb executed!

You may use the synonyms monad define or verb define instead of 3 : 0, and dyad define instead of 4 : 0.


Executing an Explicit Definition: Private Namespaces

When an explicitly defined verb is invoked, the body is recovered and the sentences in it are executed one by one.

Before the body is executed, a new private namespace is allocated for the execution. The private namespace is visible only to the sentences of the executing body (not their descendants), and holds those names that have been assigned by private assignment by sentences in the body. Names defined in the private namespace hide any nouns of the same name that have been globally defined. The private namespace and its nouns disappear when the explicit definition terminates.

Private assignment uses the assignment word =. . Public assignment uses the assignment word =: and produces a name that is available to any verb.

Before the body starts executing, the interpreter privately assigns the name y with the value of the right operand of the invocation of the verb. If the invocation is dyadic, the interpreter privately assigns the name x with the value of the left operand.


The Result Of A Verb

The result of an explicitly-defined verb is the result of the last sentence executed from the body of the definition.

Actually, it's the last sentence that is not part of a T-block.

The result of a non-explicit verb is the result of the modifier or primitive that defines the verb.

The result of a verb must be a noun.

It's easy to violate this requirement by accident. A puzzling  syntax error then arises. See: Vocabulary/ErrorMessages#syntaxresult.