Your reward for persevering through two dozen chapters on J is to be shown the direct equivalent of if/then/else, for, and while. I have waited until I am sure you realize that you don't need them, and will choose them not because you see no other way to solve a problem, but because you think they are the best way.
if., while., and the rest are classified as control words in J. Their part of speech is 'punctuation', like a parenthesis or LF character. They are allowed only inside explicit definitions, that is to say inside right operands of the : conjunction. If you want to use them from the keyboard or in a script, you must define a verb/adverb/conjunction and then execute it. A control word ends any sentence to its left, as if the control word started with an end-of-line character. We will cover only a few important control sequences here; to find the rest, bring up the J Vocabulary by pressing F1 and click on Controls which is hidden in plain view next to the heading "Vocabulary".
for./do./end. and for_x./do./end.
The allowed forms are:
for. T-block do. block end.
for_x. T-block do. block end.
The T-block is evaluated and its result A (that is, the result of the last sentence in the T-block) is saved. block is executed once for each item (item, not atom) of A . If you use the handy for_x. form (where x represents any valid name of your choice), the private variables x and x_index are created, and every time block is executed, x_index is assigned the index of an item of A and x is assigned x_index { A .
The break. and continue. control words do what you would expect.
while./do./end. and whilst./do./end.
The allowed forms are:
while. T-block do. block end.
whilst. T-block do. block end.
while. corresponds to while and whilst. corresponds to do while. The 'st' in whilst. stands for 'skip test' (the first time through), so you get one free pass through the loop, just as with do while.
The break. and continue. control words do what you would expect.
if./do./else./end., if./do./elseif./do./end.
The allowed forms (with optional components underlined) are:
if. T-block do. block else. block end.
if. T-block do. block elseif. T-block do. block... end.
The flow of control is as you would expect. T-blocks and blocks are both sequences of zero or more J sentences. The result of the last sentence in a T-block provides the result of the T-block . The result of a T-block tests true if its first atom is nonzero, or if it is empty, or if the T-block was empty. The flow of control is as you would expect based on the tests. The sequence elseif. T-block do. block may be repeated as often as desired, but you will be surprised to learn that once you code an elseif. you are not allowed to use else. in the same control structure: no loss, since an empty T-block tests true, and you can just code elseif. do. for the last block.
My antipathy for for. and while. has scarcely been concealed, but I harbor no ill will toward if. . As long as you don't apply it in a loop, if. makes the structure of code obvious and you may use it without remorse. Examples are legion; the form
if. # name =. sentence to create an array do.
code to
process name, which is now known to have items
end.
is the most common in my code, used to guarantee that a block of code is executed only when a certain noun has a nonzero number of items.
When we first learned about verb definitions we said that the result of a verb was the result of the last sentence executed. Now we must emend that statement: the result is the last sentence that is not part of a T-block.
try./catch./catcht./end. and throw.
The simplest form (see the Dictionary for others) is:
try. block1 catch. block2 end.
try./catch./end. is the control-structure equivalent of u ::v . block2 is executed only if there was an error during the execution of block1 .
If you want to signal an error, execute the foreign 13!:8 y where y is the error number you want to signal. You can use this in a try. block to transfer execution to the corresponding catch. block.
throw. aborts the explicit definition that is running, and looks in higher-level explicit definitions for a catcht. block to execute. If the previously-running explicit definition was executing in block1 of a try. block that contains a catcht., execution resumes with that catcht. block; otherwise, that explicit definition is also aborted, and the search continues in the next-most-recent explicit definition. If this search does not find a catcht. block to execute, the entire executing sentence is aborted, producing no result.
select./case./fcase./end.
The form is:
select. T-block0 case. T-block1
do. block1... end.
T-block0 is evaluated; then the T-blocks of the case. control words are evaluated sequentially until one is found that matches the result of T-block0; the following block is then executed, after which control passes to the sentence following the end. .
fcase. is like case. except that after the block of an fcase. is executed, control passes to the next block rather than to the sentence following the end. .
A T-blockn matches the result of T-block0 if the result of T-block0 is an element of the result of the T-blockn. So, a T-blockn could be 2;3;5 and any of those three values would match it. Before this check is made, each side of the comparison is boxed if it is not boxed already. An empty T-blockn matches anything.
return. ends execution of the definition that is running. The result of the last sentence not in a T-block is the result. Example:
if. T-block do. return-value return. end.
assert. sentence
assert. fails with an assertion failure error if the result of executing the sentence contains any atoms that are not equal to 1. Note that there is no end. corresponding to the assert., so there may be only a single sentence rather than a T-block.