# Tacit programming

Tacit functions apply to 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.

Known dialects which implement trains are Dyalog APL, dzaima/APL, ngn/apl and NARS2000.

## Primitives

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

      plus ← +
times ← ×
6 times 3 plus 5
48


## Derived functions

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

      Sum ← +/
Sum ⍳10
55

Dot ← +.×
3 1 4 dot 2 7 1
17


## Derived operators

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

      1(+⍣2)10
12
Twice ← ⍣2
1 +Twice 10
12


## 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. f, g, and h are functions (which themselves can be tacit or not), and A is an array. The arguments are processed by the following rules:

### Forks

A 3-train is a fork:

  (f g h) ⍵  $\Leftrightarrow$ ( f ⍵) g ( h ⍵)  ⍺ (f g h) ⍵  $\Leftrightarrow$ (⍺ f ⍵) g (⍺ h ⍵) 

The left tine of a fork can be an array:

  (A g h)  $\Leftrightarrow$ A g ( h ⍵)  ⍺ (A g h) ⍵  $\Leftrightarrow$ A g (⍺ h ⍵) 

### Atops

A 2-train is an atop:

  (g h) ⍵  $\Leftrightarrow$ g ( h ⍵)  ⍺ (g h) ⍵  $\Leftrightarrow$ g (⍺ h ⍵) 

Only dzaima/APL allows (A h), which it treats as A∘h. See Bind.

## Debugging

In Dyalog APL, analysis of trains is assisted by a user command ]Boxing on. This is achieved by executing the command ]Boxing on 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:

      ]Boxing on
Was OFF
((+.×⍨⊢~∘.×⍨)1↓⍳)     ⍝ the train to be analysed
┌───────────────────────────────┬───────┐
│┌───────────┬─────────────────┐│┌─┬─┬─┐│
││┌───────┬─┐│┌─┬─┬───────────┐│││1│↓│⍳││
│││┌─┬─┬─┐│⍨│││⊢│~│┌───────┬─┐│││└─┴─┴─┘│
││││+│.│×││ │││ │ ││┌─┬─┬─┐│⍨││││       │
│││└─┴─┴─┘│ │││ │ │││∘│.│×││ ││││       │
││└───────┴─┘││ │ ││└─┴─┴─┘│ ││││       │
││           ││ │ │└───────┴─┘│││       │
││           │└─┴─┴───────────┘││       │
│└───────────┴─────────────────┘│       │
└───────────────────────────────┴───────┘


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

      ]Boxing on -trains=tree
Was ON -trains=box
((+.×⍨⊢~∘.×⍨)1↓⍳)     ⍝ the train to be analysed
┌───┴───┐
┌─┴─┐   ┌─┼─┐
⍨ ┌─┼─┐ 1 ↓ ⍳
┌─┘ ⊢ ~ ⍨
.     ┌─┘
┌┴┐    .
+ ×   ┌┴┐
∘ ×


Or fully parenthesised:

      ]Boxing on -trains=parens
Was OFF -trains=box
((+.×⍨⊢~∘.×⍨)1↓⍳)     ⍝ the train to be analysed
(((+.×)⍨)(⊢~((∘.×)⍨)))(1↓⍳)


## 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.

### Plus and minus

      (+,-) 2     ⍝ ±2
2 ¯2
5 (+,-) 2   ⍝ 5±2
7 3


### Arithmetic mean

      (+⌿÷≢) ⍳10       ⍝ Mean of the first ten integers
5.5
(+⌿÷≢) 5 4⍴⍳4    ⍝ Mean of columns in a matrix
1 2 3 4


### Fractions

We can convert decimal numbers to fractions. For example, we can convert $2.625$ to the improper fraction ${\tfrac {21}{8}}$ with

      (1∧⊢,÷)2.625
21 8


Alternatively, we can convert it to the mixed fraction $2{\tfrac {5}{8}}$ with a mixed fraction:

      (1∧0 1∘⊤,÷)2.625
2 5 8


### Is it a palindrome?

      (⌽≡⊢)'racecar'
1
(⌽≡⊢)'racecat'
0


### Split delimited text

      ','(≠⊆⊢)'comma,delimited,text'
┌─────┬─────────┬────┐
│comma│delimited│text│
└─────┴─────────┴────┘
' '(≠⊆⊢)'space delimited text'
┌─────┬─────────┬────┐
│space│delimited│text│
└─────┴─────────┴────┘


### 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}}}$ Root ← *∘÷⍨              ⍝ Nth root
Norm ← 2 Root +.×⍨       ⍝ Magnitude (norm) of numeric vector in Euclidean space
Unit ← ⊢÷Norm            ⍝ Unit vector in direction of vector ⍵
InDirOf ← (⊢×+.×)∘Unit   ⍝ Component of vector ⍺ in direction of vector ⍵
3 5 2 InDirOf 0 0 1      ⍝ Trivial example
0 0 2


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.

      ((+.×⍨⊢~∘.×⍨)1↓⍳)17 ⍝ Accursed train
666


First, ((+.×⍨⊢~∘.×)1↓⍳) is supplied with only one argument 17 and is thus interpreted monadically.

Second, (+.×⍨⊢~∘.×⍨)1↓⍳ is a 4-train: reading right-to-left, the last 3 components are interpreted as the fork 1↓⍳ and the 4-train is interpreted as the atop (+.×⍨⊢~∘.×⍨)(1↓⍳). Similarly, (+.×⍨⊢~∘.×⍨) is also a 4-train and interpreted as the atop +.×⍨(⊢~∘.×⍨).

Thus the accursed train is interpreted as ((+.×⍨(⊢~∘.×⍨))(1↓⍳))17. Having read the train, we now evaluate it monadically.

      ((+.×⍨(⊢~∘.×⍨))(1↓⍳))17 ⍝ Accursed train as an atop over a fork atop a fork
+.×⍨(⊢~∘.×⍨)1↓⍳17       ⍝ Atop evalution
+.×⍨(⊢1↓⍳17)~∘.×⍨1↓⍳17  ⍝ Fork evalution
+.×⍨(1↓⍳17)~∘.×⍨1↓⍳17   ⍝ ⊢ evaluation
+.×⍨2 3 5 7 11 13 15 17 ⍝ numbers 2 through 17 without those appearing in their multiplication table are primes
666                           ⍝ the sum of the squares of the primes up to 17


Note that ((⊢⍨∘.×⍨)1↓⍳) is a train computing primes up to the given input.

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

      (⍎⊢,⍕∘≢)'((+.×⍨⊢~∘.×⍨)1↓⍳)'                    ⍝ Accursed train 2.0
⍎(⊢,⍕∘≢)'((+.×⍨⊢~∘.×⍨)1↓⍳)'                    ⍝ 4-train intepreted as an atop
⍎(⊢'((+.×⍨⊢~∘.×⍨)1↓⍳)'),⍕∘≢'((+.×⍨⊢~∘.×⍨)1↓⍳)' ⍝ fork evaluation
⍎'((+.×⍨⊢~∘.×⍨)1↓⍳)','17'                      ⍝ ⊢ evaluation and ⍕∘≢ evaluation
⍎'((+.×⍨⊢~∘.×⍨)1↓⍳)17'                         ⍝ , evaluation
666                                                  ⍝ ⍎ executes original Accursed train