Where to Start
[Draft for commentary and/or amendment before adding links to and from it.] [* notes important terms for cross-reference analysis. New-term introductions should be formatted distinctively. Examples should be added.]
Computer Programming for Data Processing
A datum is a unit of thought. The size of a unit may vary, from species to herd, to ideal representative, to particular individual. These are not independent data, but nested, each portion relevant to a different level of scrutiny. Data stored in digital computers are stored as sequences of elemental physical signals or states, each usually depicting one of two "binary" values. Humans relate to these sequences by grouping them into very short "bytes", and those into moderate-length "words", and then assigning more familiar meanings to them as graphical characters or numerical values. All of these meanings are determined primarily by the designers of each machine.
Computers communicate with laboratory equipment and controlled machinery through various devices designed for each application. Humans communicate with computers through sequences of characters, either directly, through speech or print converters, or through stored copies of computer values.
A programming language is a tool of thought. It helps humans analyze how they will need data processed for a particular purpose. It then enables them to construct sequences of computer values instructing a computer how to receive data, process it, and return values derived from it. J offers well over one hundred types of computational actions, which programmers prescribe via character sequences composed of letters, digits, and symbols, specifying numerical or textual values, operational symbols or names, and punctuation or controls to direct the operational sequence.
Overview
The J programming language is classed as an algebraic language, since nearly every feature is activated in sentences styled much as mathematical "formulas", composed in a very uniform syntax (deviating slightly at times from traditional notations). It is also classed as a functional language, in part for the same reason, but also because each program acts on one or two supplied data values to create and deliver a third, which is therefore some function (however convoluted) of the inputs. Unlike many programming languages, it has many features which can succinctly direct the manner in which such functions are to be applied to structured data in each context.
J is implemented as an interpreter, acting directly on the provided symbols without first translating the whole process into machine-level instructions. This permits direct entry from a keyboard for execution of one sentence for an "immediate" result, much like a small calculator, but this "calculator" may also call up a whole suite of pre-stored program sentences.
Following the terminology of natural languages, J's function definitions are called verbs, its data values nouns, its action modifiers adverbs, and its action combiners conjunctions. Nouns are rectangular arrays of atoms, which are numbers (specified in various ways appropriate to the type of usage), ASCII (or Unicode) characters, or boxes enclosing other arrays. Each array has a rank (dimension), shape (list of axis lengths), and datatype (numeric, character, or box). Arrays are built in program steps--some by derivation from input data, and some by generation via primitive operations of the language. A data array is easily generated by specifying a shape and values to fill it, such as a repeated constant or pattern, or consecutive integers.
A J program is a sequence of one or more J sentences, definining values or actions in one of the four parts of J "speech". A script of one or more programs, including comments, may be stored in a text file created by any means. A *load command may read a script, store its definitions, execute its commands, and wait for more user directives.
An array may be rearranged by shifting or rotating along a chosen axis, by transposing any axes, by adding an axis, or by flattening some axes. An array may be restructured by deleting, inserting, appending, or enclosing rows or columns. Two arrays or sub-arrays of the same shape may be combined, element for element, by addition or other arithmetic or logical operation, or with one's values selecting from the other. Values in two arrays of differing shape may be similarly combined along specified axes whose lengths agree or when one is an atom.
A signal advantage of the language is that it can deal with the whole of an array as one step of a computation, reducing program bulk and often permitting optimized computation. This also simplifies specification of an action, and recognition of its intent without needing to correlate effects of multiple loop limits. Accomplishing several such steps in one line of code can further aid understanding of a process. Additional compaction results from naming each of the primitive objects of the language with only one to three characters--alpha- and non-alphanumeric symbols--which require some initial study for familiarity; more familiar alphabetic names for them can be added in the language of your choice.
J-interpreter code is available from jsoftware [1], in versions for several popular computing devices, free for downloading. It is relatively compact and runs efficiently.
Practicing
Before *downloading your own copy of the J *interpreter, you may wish to practice evaluating various J-phrases on the web sites riju [2] or j-playground [3].
The J interpreter is ready to receive a *command *sentence when it positions the *cursor 3 (or 6) spaces from the left margin on the empty next line. Any result will appear on following lines--although some results may be empty, and show only another *input prompt.
If you have a local copy of J, you may open it by clicking on one of the J-shaped *icons in your Applications directory/folder, for either a direct typewriter-like *console version, a browser-mediated version (*Jht), or a more fully equipped multi-window version (*Jqt). A session may be terminated by "exit 0".
References
Visit NuVoc [4] for a table of all the ASCII character combinations constituting a word which represents a primitive object in the J language. Always keep in mind that, as happens in natural languages, about three-quarters of these words have multiple context-dependent meanings. The table shows names for their separate uses, each linked to a relevant descriptive page.
An expanded version, devoting a single line to each primitive action with a brief summary of its use, is available at jcheatsheet [5].
There is also a printable 2-sheet reminder, with terse examples, at RefCard [6]. There have been very few changes in the language since that production.
Data
All *data values in J are stored as multi-dimensional rectangular array structures, composed of characters, numbers, or boxes containing other arrays.
An individual *number, *character, or (single, shapeless) box containing any array, is treated in J as an atom. A linear succession of atoms is called a list, or rank-1 array, since it has a single axis (dimension)--an ordering relation by succession. The shape of (monadic $) a list is the same as the tally (monadic #) (or count) of its atoms.
A stack constructed from several equal-length lists has a new, primary, axis, creating a *list of lists, called a table or rank-2 array. The (top-level) component lists are called the items of the table. A rank-n array is a list constructed from items which are arrays of rank (n-1) and have a common shape.
An atom is an array with no axes, so of rank 0, empty shape, and *tally 1. An empty list contains no items, has tally 0; its *shape is 0, not empty. The number 0 has shape empty (an object, but having no axes), tally 1. An empty array has shape containing a 0 (at least one vacant axis), tally 0. An empty array is useful as a form, determining how later atoms or lists may be most appropriately attached. See Creating an Empty List.
A numerical value (atom) may be *entered as a literal (constant) string of *digits, possibly including an embedded *decimal point and/or various *letters denoting *base, *power of ten, power of e, power of pi, *complex component, complex angle (radians or degrees), complex radius, and rational or extended *precision. A list of numbers may be entered with consecutive items separated by one or more *blank spaces. (Comma separators can also join the atoms, but they represent distinct operations repeated during each execution, and leave the final atom vulnerable separately to action by a following verb.)
A list of ASCII (or Unicode) characters (atoms) may be entered consecutively, introduced and terminated by single *apostrophes (') (often termed "quotes" in this context). Apostrophes within the list must each be *doubled to be so recognized.
A third type of atom is an enclosed [7] (monadic <), or boxed array--an array of any shape or type to be treated as an atom in nearly all operations, excepting disclose, or open [8] (monadic >), and fetch [9] (dyadic {::).
Every atom of an array must be of the same datatype--number, character, or box. Datatypes and shapes within components of a box array need not be the same from one to another--one of the main reasons for box use.
Names
Each primitive word is a *name for one or two primitive (pre-defined) operations, of various parts of J-speech. 21 control-word exceptions function as forms of punctuation, directing the sequence of sentence performance during execution.
User-defined operations and values may be given names in a slightly *restricted format. They may use (lower- and upper-case) *letters (required for the leading character), *digits, and singly-occurring *underscores: Numbers and Names are all Words.
Sentences
In a natural language, a written or printed sentence is a linear successions of characters, each terminated by a suitable mark of *punctuation. In a J session, each sentence prescribing some computation consists of exactly one logical input line. Its *characters are *parsed syntactically into tokens, each representing a primitive operation, a *literal data value, a *name associated with an operation or value, or a punctuation mark to define subgoupings.
Sentences may include the left primitive [10](dyadic [), to ignore the result on its right (which may have been stored), essentially breaking the sentence into two which are performed sequentially. There are also several control words which act as logical line ends, separating sentences on one physical line.
Blank spaces are required only in number lists, between alphanumeric names and numeric literals, and often before *colon or *period primitives--since many other primitive tokens terminate with these characters as inflections. Sentences written without extra blanks can save a bit of display space, but often delay comprehension because the reader's mind has to go through the same token-recognition process that the interpreter does, and can be more easily derailed; blanks demarcating clusters of closely related tokens can help. Multiple *blanks may be used for clarity by indenting, setting off subordinate sections, or aligning--as for comments. (The Tab control character is not accepted in a JHS interactive session.)
Data values, the objects of computation, are termed nouns. A literal or computed value may be associated with a name, which will then be treated as a noun until it receives a non-noun value, or is *erased. While the name is being used for various data values, it is reasonable to term it as referring to a "*variable". (A name encountered before it has been given a meaning will be treated as a verb, to be defined later, but will trigger a Value error if called for in execution.)
A verb (operation, function, routine) may be followed by a literal or computed noun right argument, and perhaps preceded by one on its left. The presence of only a right argument signals a monadic interpretation of the verb name; two arguments require a dyadic interpretation. Verbs which need more than two data values may receive them *packed together, possibly enclosed in boxes, into one or two arrays which can be unpacked within the verb. (All verbs could therefore be monadic, but the availability of dyadic notation reduces the overhead of packing data items, and offers the flexibility of conveniently signaling alternate operations.)
A verb, or a verb *phrase, may be followed by a modifying adverb, and possibly a controlling *parameter, closer than the verb's right argument, forming a (longer) verb phrase. An adverb may direct the verb's *application to arguments' items separately, or to subsets, or in a different order.
A verb phrase may be joined to an adjacent verb phrase by a conjunction, so that they act together on supplied arguments. A conjunction may specify whether the later (left) verb acts immediately on each item of the earlier verb's result, or whether they are buffered for collective action, only after all its items are processed. Others may ....
Parentheses, the only *punctuation characters besides apostrophe, are used to *group sub-computations, *nested to any depth, to be performed before outer ones. Parentheses have no other computational significance. Also, they are the only grouping symbols in J; each square, curly, or angle "*bracket" is assigned another meaning individually.
Some characters normally termed as punctuation--period, colon, semicolon, comma--are used independently as *primitives, and the first two are also *inflection marks to create additional primitive symbols. The *apostrophe (') is used syntactically only to enclose characters representing themselves as data.
Sentences have a high *length *limit. When displayed, a long sentence can require horizontal scrolling for full viewing. Result output, however, has a more modest limit, at which it will be truncated and followed by '...'.
Interpreting Sentences
Sentence *recognition begins at the left end, noting the extents of successive *tokens and identifying their types and meanings.
A token NB. may follow a sentence, terminating it and introducing commentary on the rest of the line. Comment-only, and empty, lines are accepted.
Interpretive *computation begins at the right end of a sentence, *evaluating each *noun, applying *adverbs and *conjunctions to relevant *verbs, then applying verb phrases to their [left and] right *argument[s]. Even when verbs are bound together by conjunctions atop (@), at (@:), dual (&.), appose (&:), or under (&.:), to be applied together, the same order is followed.
Verbs do not have implicit relative *precedence rankings; they are performed in *right-to-left order within each parenthetical grouping.
- Results of verb application are usually nouns, to which further-left verbs may be applied.
An assignment, local (=.) or global (=:), copies the right-argument value to left-named *storage location(s) before passing it on. (A bare = denotes a comparison instead.)
The value of the *final operation of a sentence entered at the terminal is passed to the session *display, unless it was assigned to storage.
Storing Programs
A sentence which, if enclosed in parentheses, would be capable of acting on [left and] right data value[s], may be *assigned to a *name; that name may then be used as a *verb performing those actions. A verb accepting a single right-side argument is called *monadic; *dyadic verbs accept a left-side argument as well; a symbol which serves for monadic and dyadic uses is termed bivalent--whether or not the two uses are closely related.
A sentence consisting of a single *primitive token may be *assigned to a more memorable *name, after which either may be used to specify the same operation. Many such names are already defined. Before you create a name, you may enter it to see whether it is already there; you may then decide to use or to override the predefined version.
A sentence mentioning [x and] *y may be enclosed in *apostrophes, forming a character-valued noun. That noun may be used as the right argument of definition (dyadic :) along with a left argument of 3 (verb), designating the result as a possibly *bivalent verb; 4 (dyad) specifies *dyadic only. The result may be associated with (stored under, assigned to) a *name, or *embedded in another sentence. When the verb is activated, x will be given an initial value from the left argument, and y gets the right-argument value.
The local names x and y may be used in any sentence, where they will refer only to values assigned, by initialization or local assignnment (=.), in the *currently active verb, and will *disappear when that completes.
When a verb is *activated, its sentences are performed in *sequence, except where exempted by a conditional *if.-do.-end. sequence, chosen by a *select.-case.-end. sequence, or repeated by a *for.-do.-end. sequence. It *terminates after executing the final sentence, or a return. control. The verb *delivers its last computed (non-test) value to the point from which it was called.
A sequence of J-sentences stored in a *text *file, created by any means, is called a script. A load command, given a boxed character string identifying the script's *location, executes those sentences in the current session until it finishes or encounters an error, then resumes *interactive operation.
Input and *Output
*Data values may be included as *literals in sentences entered in a script or an *interactive session
Multiple lines of data--character or numerical *tables--may be *created by specifying a left argument of 0 (noun) to the define verb (:). The lines do not need to have a common length--they get strung together, separated by Linefeed characters. One cut operation (<;._2) can produce a list of separately boxed lines; another (];._2) can convert the list to a table, *blank-filled to a common width.
A stored value (of any type) may be *displayed directly by *entering its *name. *Extracts of rows and/or columns may be selected for display by use of from (dyadic {) or copy (dyadic #).
Character lists denoting numerical values can be converted to *internal *formats by 'numbers (dyadic ".) using a left argument to replace any ill-formed items. (Data in a fixed format which may run together, or which contain non-numeric items, will need preprocessing as characters before conversion.)
Data values *display in their most compact *format, up to a default *precision, with array *columns aligned at the minimum suitable width. They may, however, be presented in other chosen formats by dyadic use of format (":).
Values computed during *execution of lines within a *defined verb are not *displayed, even if not stored as a *last operation, except for the result of the initiating verb. *Intermediate *results may be displayed smoutput, session-manager output.
Filing
Any array may be written to separate *storage areas by the *foreign (system-specific) verb *filewrite??, which takes a list of bytes and a boxed character-list filename. Data may be *converted to a byte list by any process--preferably one which can be reversed after retrieval by *fileread??.
Array Manipulations:
Structuring
Array results are *displayed as rows of rank-1 lists, grouped consecutively into rank-2 tables, which are grouped with single-line spacing into rank-3 bricks. Higher-rank groupings repeat with spacings increasing by one more line per rank increase.
The *shape verb (monadic $) reports a list of the *sizes of successive *axes of an array. The axes are numbered downward/inward from the top/outside, 0 through n-1. *Tally (monadic #) reports the size of the *leading axis, the number of *items.
If the shape list of an array contains a 0, it contains no atoms, it is one form of *empty array. (It may yet contain many items, being empty lists or tables.) The shape-0 arrays of no numbers (0$0) or no characters () are equivalent, and called *null. The boxed null value is called *ace.
Constructing
Lists of characters may be *entered directly, with one *apostrophe at each end.
Lists of numbers, expressed in various formats, may be entered directly, separated by one or more *blanks between each pair.
An array of any shape composed of copies of a single value, such as 0, is easily constructed by *reshape (dyadic $) acting on that atom by a shape list: 2 4 3 $ 0 .
If more than one atom is supplied to reshape, the item rows are *filled by consecutive *copies of the supplied atoms, *repeated as needed and carried across the constituent lists, tables, etc.
An array of any shape may be filled with unique integers in sequence, using the *integers verb (monadic i.), as in i. 2 4 3 .
An array of *rank n may be promoted to a single-item array of rank n+1 by *itemize (monadic ,:).
Selecting
The three main modes of selecting portions of an array are via *dimensionality (rank), *position number (*index), or by position *flag (*mask).
Operations may be directed to operate on smaller units of an array by supplying a rank specification to a verb via the rank conjunction ("). It specifies the rank of argument *cells to which the verb should be applied. The shape formed by the group of cells concerned, their *frame, is a prefix of the shape of the whole array. The results of the individual applications are re-collected within a similar frame. The net result may be of different rank from the original if the verb results differ from the rank of the cells. (If sizes or ranks of the cell results vary, they will be *filled with *default values to the maximal rank and size among them.)
The *take verb (dyadic {.) copies a specified number of items from the beginning of a list; drop (dyadic }.) copies the items after skipping some. Operations for convenience when specifying a single-item selection or deselection are: *head (monadic {.), *tail (monadic }.), *behead (monadic {:), *curtail (monadic }:).
The *from verb (dyadic {) uses a list of item (row) numbers for an array to copy those indicated (*indexed) items into a new array. A boxed index list may be *appended to another, which will *select items within the items first selected, so that separate applications are not needed. The *copy (dyadic #) verb applies a same-length list of 0's and 1's to a list of items (of any rank), copying only those corresponding to 1's. The *selector is usually the result of testing the item values for satisfying some condition, but may also be a constant, or generated algorithmically or randomly. (Selector values greater than 1 make *multiple copies; a *complex selector inserts a specified number of zero, blank, or ace items following the copied-value group.)
*Nub (monadic ~.) retrieves only the first appearance of each *unique value.
Operations on an array do not make any lasting *change to it unless and until the new version is *assigned to that name; many operations merely modify pointers or copy portions, so that few atoms need to be shuffled or replaced--especially if the result is promptly stored back under the same name.
Joining
Two arrays, composed of the same datatype of atoms, may be *consolidated in several ways:
--Horizontally, by making a list of wider lists, by *stitch (dyadic ,.). The sizes (lengths) of the two lists (arrays) must match.
--Linearly, making a longer (taller, deeper) list, by *append (dyadic ,).
--Vertically, making a higher-rank stack of tally 2, by *laminate (dyadic ,:).
Wherever the shapes (sizes) of the two array's items do not match, the smaller items are *extended by appropriate *fill atoms (0, blank, or empty box) to the greater size.
Whenever arrays of *different types need to be joined, an open (unboxed) component must first be *boxed (monadic <) to join with another (boxed) component. *Link (dyadic ;) will box either argument which is supplied unboxed, then appends.
Rearranging
The items in a list may be copied in reverse *order by *reverse (monadic |.) All the items of a list may be copied via *rotate (dyadic |.) as if rotated toward the front/top by a specified amount, with the dropped items re-entering at the far end. A negative rotation moves items in the opposite direction.
Specifying a *fill atom with rotate (dyadic |.!f, where f means some atomic-valued expression) prevents the wrap-around, with vacated positions being filled instead with f-atoms, replicated to the shape of the those items.
*Transpose (|:) copies an array witb *axes interchanged, as if viewing a block from a different direction and/or in a mirror. Monadic transpose copies with the ordering of all the axes reversed. Dyadic transpose specifies, in order, which axes are to be moved to the end of the group. (Some operations are more convenient, or only possible, to apply to the leading one or two axes. Transpose can bring other axes to the front for such an operation, then move them back afterward.)
*Gradeup (monadic /:) lists the *indices in its argument which would extract its values in increasing aphabetic or numerical order. *Sortup (dyadic /:), applied to the same array on left and right, gives its values in increasing order. A different left argument (of the same length) is sorted according to the values on the right. *Gradedown (monadic \:) and *sortdown (dyadic \:) produce the opposite orderings.
Deconstructing
All the atoms of an array of any rank may be copied into a single list by *ravel (monadic ,).
Each of the rank-(n-1) items in an array may be separately raveled by ravel items (monadic ,.), forming a table.
Each item of a boxed list may be opened and appended to the others by *raze (monadic ;), to form a less-deeply boxed array.
When a large computation is approaching the limits of storage capacity, assigning an *empty value to a name previously used for a very large array can free up storage for following steps.
Combining
Producing the negation of all the values in an array is easy--apply *negate (monadic -) to it. Negate has *default rank of 0, so that it applies to each atom individually.
Adding corresponding atoms of identically shaped arrays is also simple--apply them as left and right arguments to *plus (dyadic +). Plus has default left and right ranks of 0, so that it applies to individual atoms, *pair by pair. The result therefore has the same shape as either argument.
Numerous other *arithmetic, *relational, and *logical operations are performed by monadic or dyadic verbs with similar *structural properties.
Values from arrays of *differing rank may also be combined, by specifying how parts of each are to be paired up. The combining verb may be given the ranks of the parts of the left and of the right argument which are to be matched. A rank conjunction (") specifying 1 2 indicates that each list of the left argument is to be applied to each table of the right argument. Multiplying values in a list by those in a table means multiplying the left list by each list composing the right table, which requires only that they have the same length. Rank 2 1 would multiply each list in each table composing the left argument by the one list on the right.
Specifying ranks as 0 1 denotes combining each left atom singly with the whole of each row in the right argument. The left argument should be of the same length as, not the length of those lists, but their number.
*Copy (dyadic #) has default ranks of 1 _; lists of equal length are required, but the length of the result is determined by the sum of the left-argument (real and imaginary) values. The right rank of *infinity indicates application to the whole of the argument, effectively its own rank, n; since it is a list of lists, the length of the left argument must match the number of rank-(n-1) items on the right, the first number in its shape list.
Repeating
The basic mode of repeated array combination is specified by rank, operating in *parallel, where action on each pair of values does not depend on or affect action on others. J also has two types of *serial processing, where each set of results is used in the next set.
One mode is typified by the adverb *insert (/), which applies a verb "between" successive atoms of a single argument, as when summing a list. When two arguments are present, it is applied to each possible pairing of their items, producing a *table ("Cartesian product") of results.
Other adverbs may be used to apply a verb to: successive *infixes (dyadic \) or *outfixes (dyadic \.) of an argument; increasing *prefixes (monadic \) or decreasing *suffixes (monadic \.); *oblique extracts (monadic /.); or items associated with common *key values (dyadic /.). The *cut conjunction (;.), as modified by a following selector constant, directs the preceding verb to apply to various types of partitions of its argument.
Another mode is a more traditional use of for. and do. *controls to introduce a section of code, terminated by end., to be *repeated.
Errors
If the interpreter encounters an error, it announces the *type of error, displays the sentence being executed, and displays a *caret under the token it was trying to process. Some common errors are:
--*Value error: name is *undefined
--*Syntax error: *wrong order of nouns, verbs, or other parts of speech
--*Domain error: wrong number or wrong type of argument[s] to a verb
--*Length error: *mismatch of argument shapes (on some axis)
--*Rank error: mismatch of argument ranks
The system-supplied command " *dbr 1" turns on *debugging assistance. Following an error, execution within the current verb is *suspended, holding current *local values for inspection, and awaiting further action. The input *prompt doubles to six spaces as a reminder of the suspended *environment.
If correcting a value or a faulty sentence can correct that error, you may enter a sentence or more to achieve what was intended, then enter " *dbnxt" to *resume execution at the following line.
The command "dbr 0" will *clear off the last uncleared suspension, returning to a previous environment. Only after all suspensions are cleared will the input prompt return to the normal three spaces.
Features to Explore
Tree-structured data are easily represented as lists of lists. Arrays of boxed values can accommodate lists of varying length, to almost any depth of boxing. The verb *levelof (monadic L.), conjunctions *levelat (L:) and *spread (S:) are particularly useful in *tree manipulations.
Additional capabilities are present to assist with number *conversions and computations in mathematics (including number theory, linear algebra, permutations, convolution), engineering, probability, statistics, data management, and graphics.
Two anomalous *syntactic features facilitate *tacit programming, which distributes arguments to multiple verbs without explicitly naming them. Two adjacent verb phrases bounded by parentheses are termed a *hook; three such are termed a *fork. Arguments [before and] after the parentheses are delivered in special patterns to the contained verbs. Moderately involved computations so specified sometimes execute more quickly than equivalent non-tacit versions.
Using the *tie conjunction (`), J can create *gerunds--nouns which represent (lists of) verbs. They may be activated by explicit selection or implicitly in rotation during *multiple application.
The *makesparse verb (monadic $.) is useful for storing and displaying large arrays which consist mostly of *zeroes. The *sparse verb (dyadic $.) manages the type of storage and conversions.
Large projects may benefit from storing definitions for distinct aspects of the work in separate *scripts. When they need to work together, they may be loaded as distinct *locales. During operation, an implied locale may be specified, and *switched as needed. A named object in another locale can also be indicated, without switching the current locale, by appending the other locale's name, directly or indirectly, between double and single *underscores, to the object name. A search *path may also be defined to set the order in which to search specific locales for a name not found in the current locale.
Downloading
J systems can be installed and distributed without *charge. (*Fees may be incurred for specialized features or extensive consulting assistance.) Choose the most recent non-Beta version for your operating system, and follow the path to get all the *addons, which include a *Qt Integrated Development Environment for a multi-windowed editing, computing, and debugging *interface.
Challenging
One way to get a major benefit from this *functional programming language is to organize the actions needed for your project in small steps, each with a relevant name. Your goal is to be able to string them together into larger steps which will read, probably a bit stiltedly, as a description of the processes. When they all work well, you may apply the *fix adverb (f.) to the main verbs, to "compile" them into composites of all the primitives of their subfunctions, thus reducing instruction fetching time during interpretation.
One way to get assistance with the challenges these goals can present is to sign up to join one or more of the J-user *forums, where you may pose your own questions and read answers to yours and others'. Visit https://code.jsoftware.com/wiki/System/Forums . For history, inspiration, and tips on nearly 300 application topics, visit https://code.jsoftware.com/wiki/Essays .
- - - - -
- - - - -