Vocabulary/ModifierTrains
In J, a train is an isolated sequence of words (surrounded by parentheses or named) whose final execution is that of a bident or trident—the respective generalizations of hooks and forks.
A modifier train is a train which produces a modifier (adverb or conjunction).
Overview
The table below lists all valid fundamental sequences that create adverbs or conjunctions.
Each sequence yields a derived entity that subsequently acts on the operand(s) u [and v].
These fundamental sequences can be nested to create more complex trains.
Sequence Part of speech Interpretation Quick Search V0 V1 C2 conj V0 V1 (u C2 v) VVC N0 V1 C2 conj N0 V1 (u C2 v) NVC N0 C1 A2 adv N0 C1 (u A2) NCA N0 C1 C2 conj N0 C1 (u C2 v) NCC V0 C1 A2 adv V0 C1 (u A2) VCA C0 V1 C2 conj (u C0 v) V1 (u C2 v) CVC V0 C1 C2 conj V0 C1 (u C2 v) VCC A0 C1 A2 conj (u A0) C1 (v A2) ACA A0 C1 C2 conj (u A0) C1 (u C2 v) ACC C0 C1 A2 conj (u C0 v) C1 (v A2) CCA C0 C1 C2 conj (u C0 v) C1 (u C2 v) CCC V0 N1 C2 adv (... V0 N1) C2 VNC A0 V1 V2 adv (u A0) V1 V2 AVV C0 V1 V2 conj (u C0 v) V1 V2 CVV A0 A1 V2 conj (u A0) (v A1) V2 AAV A0 A1 A2 adv ((u A0) A1) A2 AAA C0 A1 A2 conj ((u C0 v) A1) A2 CAA A0 C1 N2 adv (u A0) C1 N2 ACN A0 C1 V2 adv (u A0) C1 V2 ACV C0 C1 N2 conj (u C0 v) C1 N2 CCN C0 C1 V2 conj (u C0 v) C1 V2 CCV N0 C1 adv N0 C1 u NC V0 C1 adv V0 C1 u VC A0 V1 adv (u A0) V1 AV A0 A1 adv (u A0) A1 AA A0 C1 adv (u A0) C1 u (adverbial hook) AC C0 N1 adv u C0 N1 CN C0 V1 adv u C0 V1 CV C0 A1 conj (u C0 v) A1 CA C0 C1 conj (u C0 v) (u C1 v) CC
Common uses
While=: ^:^:_ NB. equivalent to {{u^:v^:_}} >:While(<&7) 0 NB. increment while less than 7 7
Here the isolated word sequence ^:^:_ directly derives a conjunction, per the CCN table entry. When the verb operands >: and <&7 are passed to the derived conjunction, the latter executes on the operands, deriving another entity (in this case, a verb).
This final step is no different than that of the equivalent explicit conjunction {{u^:v^:_}} deriving a verb when passed its operands.
Classification
Each word in a modifier train can be thought of as having none (in the case of a verb or noun), 1 (in the case of an adverb), or 2 (in the case of a conjunction) slots where the operand(s) may potentially be piped in.
Most modifier trains in the sequence table can be categorized, eliminating the need for much memorization or lookup:
- a conjunction paired with a verb/noun binds the verb/noun as an operand, creating an adverb
- C-middle-tine trains pipe the operand(s) into both outer tines (where possible) and conjoin the resulting entities using the middle conjunction
- V-middle-tine trains pipe their operand(s) into both outer tines (where possible), and the middle verb is executed on the entities derived by the outer tines; usually this derives a fork when passed the operand(s)
- trains ending in AA (including AA itself) pipe their operand(s) into the left tine, and successively apply the adverbs to the derived entity
The remaining cases have ad-hoc interpretations:
- AAV --> (u A0) (v A1) V
- AV --> (u A) V
- CC --> (u C0 v) (u C1 v)
- CA --> (u C v) A
- AC --> (u A) C u
Longer modifier trains
For comparison, a verb train (that is, one whose execution derives a verb) with 4 or more tines is implicitly grouped and evaluated in 3’s from the right.
NB. implied parentheses: NB. v6 v5 v4 v3 v2 v1 v0 ----> v6 v5 (v4 v3 (v2 v1 v0))
A modifier train with 4 or more tines is explicitly grouped and evaluated in 3’s from the left:
[.@]^:].^:a: (([. @ ]) ^: ].) ^: a:
Note: This behavior assumes that contained verb/noun phrases are parenthesized—see below.
Examples
The way that longer modifier trains process operand(s) u [and v] is analogous to how longer verb trains process argument(s) [x and] y. The following diagrams demonstrate how operands u (and v in the case of conjunctions) are bound by longer modifier trains to produce a resulting modifier.
doCollectUntil=: [.@]^:(-.@:)^:a: [.
Equivalent to {{u@]^:(-.@:v)^:a: u}}.
The parts of speech in the train are:
[. @ ] ^: (-. @:) ^: a: [. C1 C2 V3 C4 (V5 C6) C7 N8 C9
The leftmost 3-train—(C1 C2 V3)—derives a conjunction, just as e.g. (+/ % #) derives a verb. For the purposes of tracing through the evaluation of a modifier train, we could say that (C1 C2 V3) is itself a conjunction.
Thus the train consisting of the first 5 entities from the left—C1 C2 V3 C4 (V5 C6)—becomes C C4 (V5 C6), where C represents the conjunction (C1 C2 V3). The isolated train (V5 C6) is an adverb, so C C4 (V5 C6) resolves to C C4 A, which is a CCA train. This in turn is a conjunction… and so on.
Evaluation is continued stepwise in 3’s from the left until the end is reached:
C1 C2 V3 C4 (V5 C6) C7 N8 C9 -------> C C4 A ----------> C C7 N8 ------> C C9 —---> C C2 ----> C4 ----> C7 C9 ----> resulting conj. /\ \ \ /\ C1 V3 (V5 C6) N8 / \ /\ | / \ u v v u v @: ----> ^: ----> ^: [. ----> resulting conj. / \ \ \ /\ [. ] (-.@:) a: / \ /\ | / \ u v v u v
(((A V V) C N) V V) A
C4 V6 V7 ----> A8 ----> resulting adv. /\ (A1 V2 V3) N5 | u
V V C A A C V
V1 V2 C3 ----> A4 ----> A5 ----> C6 ----> resulting conj. /\ \ u v V7
C V V C
((C1 V2 V3) C4) ----> resulting conj. /\ /\ u v u v
A ((C C N) V V C C)
( (C3 V5 V6) ----> C7 ) ----> resulting adv. ( /\ \ ) A1 ----> ( C2 N4 C8 ) | ( /\ /\ ) u ( u′ v′ u′ v′ )
Here u′ and v′ resolve to (u A1) and u respectively: (CCN)VVCC derives a conjunction, so at the outermost level the entire train resolves to AC --> (u A) C u.
Usage
- Just as with explicitly defined modifiers, a tacit modifier (i.e. modifier train) is usually used in an assignment, as opposed to "inline", since the primary purpose of modifiers is to abstract over the operand(s) u [and v]. Inline use can occasionally aid clarity for common idioms, e.g. u (^:^:_) v where u and v are long expressions.
- Tie (`) and Evoke Gerund as Train (`:6) can be used to insert derived verbs anywhere within a verb train:
t0=: (+/) ` ` `: 6 % t0 # +/ % #
- The AC train pipes a (potentially modified) copy of u to the right side of the conjunction phrase, similar to how the
(v0 v1) y
andv0~ y
create a copy of y on the left side of the expression.- This allows u, or modified versions of u, to be inserted in multiple places within a verb train, as in
/.([.`+`(\@])`:6)
(equivalent to{{u/. + u\@]}}
). ]: (conj. phrase)
duplicates operand u without modification, akin to how the phrasesu~ y
and(u ]) y
duplicate the y-argument.
- This allows u, or modified versions of u, to be inserted in multiple places within a verb train, as in
]. (conj. phrase) [.
swaps operands u and v, akin to howx u~ y
swaps the x and y arguments.- Ident (]:) isn't restricted to use in adverbs; it can be used within conjunctions as well. This is useful when you want one operand as-is, and the other modified by an adverb. For example,
]: / |.
equates to{{u v/ |.}}
. - Lev ([.) and Dex (].) aren’t restricted to use in conjunctions; they can be used within the conjunction phrase of the adverb-forming train AC, in which [. represents (u A) and ]. reprepresents u.
- Tacit modifiers can be juxtaposed and nested to write arbitrarily complex modifiers.
Examples of translating explicit modifier definitions to tacit
filter=: {{u # ]}}
filter=: ]: # ]
eachLeft=: {{u"_&.(>`a:)}}
eachLeft=: ]:"_&.(>`a:) NB. or ("_)&.(>`a:)
bivalent=: {{u@:v : (u v)}}
bivalent=: @: : ([.].) NB. [x] u v y
modify=: {{ u@{`[`]} }}
modify=: ]:@{`[`]} NB. or (@{)`[`]}
substr=: {{,:@[ u ]}}
substr=: ,:@[`]:`]`:6
until=: {{u^:(-.@:v)^:_}}
until=: [.^:(-.@:].)^:_ NB. or ]:^:(-.@:)^:_
Noun operands
u and v in the sequence table can be either verbs or nouns—in other words, u and/or v can be replaced by m and/or n respectively. Here we translate some simple explicit modifiers with noun operands into equivalent tacit modifiers:
uN=: {{u n}}
uN=: [. ]. - uN 1 _1
mPlusN=: {{m+n}}
mPlusN=: [.+]. 1 mPlusN 2 3
uNegateN=: {{u-n}}
uNegateN=: [.@:- ]. NB. CCVC ^ uNegate 2 0.135335
reciprocalOfM=: {{% m}}
reciprocalOfM=: %([.].)]: NB. V(CC)A NB. or %([.].) 3 reciprocalOfM 0.333333
u3=: {{u 3}}
u3=: ]:([.].)3 NB. A(CC)N NB. or ([.].)3 - u3 _3
uv3=: {{u v 3}}
uv3=: @:([.].)3 NB. C(CC)N - uv3 % _0.333333
two_u_three =: {{2 u 3}}
two_u_three=: 2&]:([.].)3 NB. NCA(CC)N NB. or (2&)([.].)3 + two_u_three 5
Experimenting with tacit modifiers
Although modifiers are usually written as assignments, passing the operands inline can nevertheless be helpful for experimenting with tacit modifiers, and verifying that a given adverb or conjunction does what you intend:
+( ]:@/\ )= +@(=/)\ +( ]:@(/\) )= +@(=/\) -( uv3=: @:([.].3) )% _0.333333 +( ([./)`;`([.\]:@])`:6 a: ) +/ ; +\@] e.( %^:(0&]:`(12"_))`]}]:"]: ::'z' )2 %^:(0&e.`(12"_))`]} "2 ::'z' e.( (%^:(0&[.`(12"_))`]})"]. ::'z' )2 %^:(0&e.`(12"_))`]} "2 ::'z'
Completeness
Modifier trains can implement any modifier except those in which a noun phrase involving arguments x and/or y is passed internally as an operand to a modifier, as in {{u"(v y) y}} or {{(u"x) y}}.
This limitation follows from the fact that tacit verbs cannot implement e.g. the equivalent of {{(<"x) y}}. The tacit stand-in for the noun x is the verb [, and e.g. u"verb has a different meaning from u"noun.
Parsing rules for mixed modifier/verb trains of longer length
Within modifier trains, sequences of more than two successive non-parenthesized verbs/nouns should not occur.
If this rule is not followed, the train will be grouped according to the full complexity of the parsing table.
- Provided that this rule is adhered to, longer modifier trains group in 3's from the left.
& & / & + + NB. even number of words ((& & /) & +)+ & & / & & + + ((& & /) & &) + + NB. odd number of words
For example, if one wants:
- (CCA)CA --> parentheses are not needed: CCACA
- (CVV)CA --> parentheses are not needed: CVVCA
- (CVV)VV or CV(VVV) or C(VVV)V--> parentheses needed; CVVVV has more than two successive V's
- (NVN)C --> parentheses are needed; NVNC has more than two successive V/N's
Notes and Examples
VVC/NVC
5 7 +/ (* ; .) * i.2 2
┌─────┬─────┐
│ 0 5│14 26│
│14 21│ │
└─────┴─────┘
Here, the conjunction on the right is initially placed into a fork (which needs some sort of good name). Initially the entire fork acts as a conjunction, and the arguments to that conjunction (here +/
and the *
on the right) are supplied to the inner conjunction, forming the verb fork * ; +/ .*
.
NOTE: NVC should appear in a future J release, but does not work in j9.6.0-beta13
VNC
+(j. 3 &) 10
10j3
The V N in VNC is evaluated to produce a noun, which becomes an instance of the NC train.
The entire expression to the left of the conjunction is evaluated and then combined with the conjunction to form an adverb - in this example 0j3&
.
VNC is the only example of a derived modifier hook which evaluates a verb during its construction.
AVV
+(/ % #) 3 5 7
5
Here, the once we supply an argument for the adverb we get a verb fork.
CVV
5 7 +/ ( . ; %.) * i.2 2
┌─────┬────┐
│14 26│_4 5│
└─────┴────┘
In this example, the fork acts as a conjunction which will form a verb fork.
CVC
+/ (&: , &.:) *: 2 3 7
62 7.87401
Here we initially have two conjunctions which after receiving their verb arguments form the verb fork +/&:*: , +/&.:*:
(sum of squares and the square root of the sum of squares
AAV
AAV forms a conjunction with each adverb accepting a different verb argument. If you instead wished a single verb argument to be composed with the adverbs, use (AA)V
.
#((/.~)]:~.)(,:;,.) 3 5 7 5 3
┌─────┬───┐
│2 2 1│2 3│
│3 5 7│2 5│
│ │1 7│
└─────┴───┘
Here, (/.~)
is an adverb which takes #
as an argument forming the verb #/.~
and ]:
is the identity adverb which takes the fork (,:;,.)
as an argument. This gives us (#/.~ (,: ; ,.) ~.)
(tallies of unique values along with those unique values, shown in rows and in columns).
AAA
-(~/\.)i.5
_2 _2 _1 1 4
An AAA train gives us simple composition rather than a fork. Thus, these are equivalent:
-(~/\.)i.5
_2 _2 _1 1 4
-~/\.i.5
_2 _2 _1 1 4
(-~/0 1 2 3 4),(-~/1 2 3 4),(-~/2 3 4),(-~/3 4),(-~/4)
_2 _2 _1 1 4
(0-~1-~2-~3-~4),(1-~2-~3-~4),(2-~3-~4),(3-~4),4
_2 _2 _1 1 4
(0-~1-~2-~4-3),(1-~2-~4-3),(2-~4-3),(4-3),4
_2 _2 _1 1 4
((((4-3)-2)-1)-0),(((4-3)-2)-1),((4-3)-2),(4-3),4
_2 _2 _1 1 4
CAA
CAA behaves similarly to AAA except the conjunction requires a second argument. (In other words, it does not follow the pattern of AAV where different adverbs take different external arguments.)
+/(&./\.)*: i.5
5.47723 5.47723 5.38516 5 4
+/(&./\.)*: i.5
5.47723 5.47723 5.38516 5 4
+/&.*:/\. 0 1 2 3 4
5.47723 5.47723 5.38516 5 4
(+/&.*:/0 1 2 3 4),(+/&.*:/1 2 3 4),(+/&.*:/2 3 4),(+/&.*:/3 4),(+/&.*:/4)
5.47723 5.47723 5.38516 5 4
...
NCA
*(0 1 1x1 1p1& /) i.3
0 0 0
0 1 2
0 2.71828 5.43656
0 3.14159 6.28319
Here, *(0 1 1x1 1p1& /)
gives us 0 1 2.71828 3.14159&(*/)
(except with greater accuracy).
NCC
+(2 & &.)^. 2 4 6 8
4 8 12 16
The example presented here for a NCC conjunction train serves as an overly elaborate mechanism to multiply by 2.
Equivalent results here include:
+(2 & &.)^. 2 4 6 8
2&(+&.^.) 2 4 6 8
^(^.2)+(^.2 4 6 8)
VCA
5 13 p:(+&.inv) 7 11
13 29
Unlike in some other examples where resolving the adverb results in a verb fork, here the inner tine is a conjunction, which is applied immediately to generate the resulting verb (no secondary fork is created).
Equivalent expressions:
5 13 +&.(p:inv) 7 11
p: 5 13 +&(p:inv) 7 11
p: 2 5 + 3 4
p:5 9
VCC
^(<.&&.)j. i.6
0j_1 1j_1 1 0j1 _1 _1j_1
Here, our derived verb is <.&(^&.j.)
ACN
+(/L:0) 1 2 3 ;<<4 5 6
┌─┬────┐
│6│┌──┐│
│ ││15││
│ │└──┘│
└─┴────┘
*(/L:0) 1 2 3 ;<<4 5 6
┌─┬─────┐
│6│┌───┐│
│ ││120││
│ │└───┘│
└─┴─────┘
ACV
5 10 -/(~&.:^.)100 1000
20 10
200 100
Here the derived verb is -/~&.:^.
which is numerically equivalent to %~/
for positive left and right arguments.
ACA
Unlike the AAA train, a ACA train is a conjunction which requires two different verb arguments:
+(/&/)*
+/&(*/)
2 3 +(/&/)* 10 100
1006
ACC
ACC is similar to ACA except that the conjunction on the right takes both of the verb arguments.
+(/ . ].)*
+/ .*
1 2 3 +(/ . ].)* 1 10 100
321
-/(~&&.:)*:
-/~&(-/&.:*:)
3 2-/(~&&.:)*:100 10
97.2627
CCN
+/(&.: & 12) *:
+/&.:*:&12
+/(&.: & 12) *: 5 9 16
13 15 20
or
while=: ^:^:_
(+ p:) while (<&10) 0
26
whilst=: ^:^:a:
(+ p:) whilst (<&10) 0
0 2 7 26
CCA
Here, the rightmost adverb takes its verb argument from the right side of the train rather than the left side.
+/( . &. ~)*
+/ .*&.(*~)
3 +/( . &. ~)* 3 4
15
CCC
A fork composed of three conjunctions works much like a fork composed of three verbs:
+(```)-
┌─┬─┬─┬─┐
│+│-│+│-│
└─┴─┴─┴─┘
(+`-)`(+`-)
┌─┬─┬─┬─┐
│+│-│+│-│
└─┴─┴─┴─┘
NC/CN
A single noun when supplied to a conjunction forms an adverb which requires the other conjunction argument:
-(3&)
3&-
-(&3)
-&3
VC/CV
A single verb when supplied to a conjunction forms an adverb which requires the other conjunction argument:
-(3&)
3&-
3(-&)
-&3
3(&-)
3&-
AV
An AV train first takes a verb argument and then (typically) forms a hook (as adverbs usually produce verb results):
+(/ *:) i.4
0 1 4 9
1 2 5 10
2 3 6 11
3 4 7 12
AA
A pair of adverbs as a train acts as an adverb, and the result of the left adverb is then combined with the right adverb. In other words, these are equivalent:
+(/\)
+/\
(+/)\
+/\
AC
The (AC) train is a hook with adverb syntax - the single argument to the hook becomes the argument of the adverb and the right argument of the conjunction (the left argument of the conjunction is the result from the adverb):
j.(~ &)
j.~&j.
1 2 3 j.(~ &) 10 100 1000
_1j10 _2j100 _3j1000
CA
The (CA) train produces a conjunction - the arguments to the train become the arguments to the inner conjunction and the result from that conjunction becomes the argument to the adverb.
10(&/.)#.
10&#./.
1 2 3 2 1 (10(&/.)#.) 1 2 3 4 5
15 24 3
CC
The (CC) train supplies both arguments to both conjunctions and as the results from conjunctions are typically verbs, the result is typically a verb hook.
-(& &.)j.
-&j. -&.j.
-(& &.)j. 2 _3 4j5
0j4 0j_6 _10j8