Tacit programming

Tacit programming, also called point-free style, refers to usage of tacit functions that are defined in terms of implicit arguments. This is in contrast to the explicit use of arguments in dfns and tradfns (which have named arguments). Some APL dialects allow to combine functions into trains following a small set of rules. This allows creating complex derived functions without specifying any arguments explicitly.

Dialects which implement trains include Dyalog APL, dzaima/APL, ngn/apl and NARS2000.

Primitives
All primitive functions are tacit. Some APLs allow primitive functions to be named.

Derived functions
Functions derived from a monadic operator and an operand, or from a dyadic operator and two operands are tacit functions:

Derived operators
A dyadic operator with its right operand forms a tacit monadic operator:

Trains
A train is a series of functions in isolation. An isolated function is either surrounded by parentheses or named. Below,  and   refer to the arguments of the train. ,, and   are functions (which themselves can be tacit or not), and   is an array. The arguments are processed by the following rules:

Forks
A 3-train is a fork: The left tine of a fork can be an array:

Atops
A 2-train is an atop:

Only dzaima/APL allows, which it treats as. See Bind.

Debugging
In Dyalog APL, analysis of trains is assisted by a user command. This is achieved by executing the command  and then entering a train without any parameters. A structure of the train will be displayed.

For example, the "accursed train" from the section below can be analysed like this:

Alternatively, a train can be represented in form of a tree: Or fully parenthesised:

Examples
One of the major benefits of tacit programming is the ability to convey a short, well-defined idea as an isolated expression. This aids both human readability (semantic density) and the computer's ability to interpret code, potentially executing special code for particular idioms.

Fractions
We can convert decimal numbers to fractions. For example, we can convert $$2.625$$ to the improper fraction $$\tfrac{21}{8}$$ with Alternatively, we can convert it to the mixed fraction $$2\tfrac{5}{8}$$ with a mixed fraction:

Component of a vector in the direction of another vector
Sometimes a train can make an expression nicely resemble its equivalent definition in traditional mathematical notation. As an example, here is a program to compute the component of a vector $$\textbf{a}$$ in the direction of another vector $$\textbf{b}$$:
 * $$\textbf{a}_\textbf{b} = (\textbf{a}\cdot\hat{\textbf{b}})\hat{\textbf{b}}$$

For a more parallel comparison of the notations, see the comparison with traditional mathematics.

The Number of the Beast
The following expression for computing the number of the Beast (and of I.P. Sharp's APL-based email system, 666 BOX) nicely illustrates how to read a train. First,  is supplied with only one argument   and is thus interpreted monadically.

Second,  is a 4-train: reading right-to-left, the last 3 components are interpreted as the fork   and the 4-train is interpreted as the atop. Similarly,  is also a 4-train and interpreted as the atop.

Thus the accursed train is interpreted as. Having read the train, we now evaluate it monadically. Note that  is a train computing primes up to the given input.

A more satisfying variation of the accursed train is the following.

Tutorials

 * Dyalog: version 14.0 release notes
 * Dfns workspace: Translation of [dfns into tacit form]
 * APL Cultivation: Transcribing to and reading trains
 * APLtrainer: How to read trains in Dyalog APL code (video)
 * APLtrainer: Function trains in APL (video)
 * Dyalog webinar: Train Spotting in Dyalog APL (video)
 * Dyalog '13: Train Spotting in Version 14.0 (video)

Documentation

 * Announcement
 * Dyalog