13 :
is documented in the vocabulary or NuVoc under :
(Explicit).
The basic idea is that the value you want to be x
becomes [
and the value you want to be y
becomes ]
. But as soon as the the rightmost token changes from a noun (value) to a verb like [
or ]
, the entire statement becomes a train, and you may need to use the verb [:
or the conjunctions @
or @:
to restore the composition behavior you had before.
You can also replace the values with the actual names x
and y
, and then wrap the whole thing in ((dyad : ' ... ')
). That is:
>:?10#6 NB. Roll ten six sided dice.
can become:
10 (dyad : '>: ? x # y') 6 NB. dyad is predefined. It's just 4.
If you only need the y
argument, you can use monad
, which is prefined as 3
. The name verb
is also 3
. I tend to use verb :
when I provide both a monadic and dyadic version, and monad
when I only need the monadic meaning.
If your verb is a one-liner like this, you can sometimes convert it automatically to tacit form by replacing the 3
or 4
with 13
.
I have some notes on factoring verbs in j that can help you with the step-by-step transformations.
addendum: psuedocode for converting a statement to tacit dyad
This only covers a single statement (one line of code) and may not work if the constant values you're trying to extract are being passed to a conjunction or adverb.
Also, the statement must not make any reference to other variables.
- Append
[ x=. xVal [ y =. yVal
to the statement.
- Substitute appropriate values for
xVal
and yVal
.
- Rewrite the original expression in terms of the new
x
and y
.
- rewrite
statement [ x=. xVal [ y=. yVal
as:
newVerb =: (4 : 0)
statement ] y NB. we'll fill in x later.
)
(xVal) newVerb yVal
Now you have an explicit definition in terms of x
and y
. The reason for putting it on multiple lines instead of using x (4 : 'expr') y
is that if expr
still contains a string literal, you will have to fiddle with escaping the single quotes.
Converting the first noun
Since you only had a pipeline before, the rightmost expression inside statement
must be a noun. Convert it to a fork using the following rules:
y
→ (])
x
→ ]x ([)
_
, __
, _9
... 9
→ (_:)
, (__:)
, (_9:)
... (9:)
n
→ n"_
(for any other arbitrary noun)
This keeps the overall meaning the same because the verb you've just created is invoked immediately and applied to the [ y
.
Anyway, this new tacit verb in parentheses becomes the core of the train you will build. From here on out, you work by consuming the rightmost expression in the statement, and moving it inside the parentheses.
Fork normal form
From here on out, we will assume the tacit verb we're creating is always a fork.
This new tacit verb isn't actually a fork, but we will pretend it is, because any single-token verb can be rewritten as a fork using the rule:
v → ([: ] v).
There is no reason to actually do this transformation, it's just so I can simplify the rule below and always call it a fork.
We will not use hooks because any hook can be rewritten as a fork with the rule:
(u v) → (] u [: v ])
The rules below should produce trains in this form automatically.
Converting the remaining tokens
Now we can use the following rules to convert the rest of the original pipeline, moving one item at a time into the fork.
For all of these rules, the (]x)?
isn't J syntax. It means the ]x
may or may not be there. You can't put the ] x
in until you transform a usage of x
without changing the meaning of the code. Once you transform an instance of x
, the ]x
is required.
Following the J convention, u
and v
represent arbitrary verbs, and n
is an arbitrary noun. Note that these include verbs
tokens y u (]x)? (fork) ] y → tokens (]x)? (] u fork) ] y
tokens x u (]x)? (fork) ] y → tokens ]x ([ u fork) ] y
tokens n u (]x)? (fork) ] y → tokens (]x)? (n u fork) ] y
tokens u v (]x)? (fork) ] y → tokens u (]x)? ([: v fork) ] y
There are no rules for adverbs or conjunctions, because you should just treat those as part of the verbs. For example +:^:3
should be treated as a single verb. Similarly, anything in parentheses should be left alone as a single phrase.
Anyway, keep applying these rules until you run out of tokens.
Cleanup
You should end up with:
newVerb =: (4 : 0)
] x (fork) ] y
)
(xVal) newVerb yVal
This can be rewritten as:
(xVal) (fork) yVal
And you are done.