# Difference between revisions of "Tacit programming"

(→Trains) |
|||

(15 intermediate revisions by 4 users not shown) | |||

Line 32: | Line 32: | ||

== Trains == | == Trains == | ||

− | A train is a series of functions in isolation. An isolated function is either surrounded by parentheses or named. Below, <source lang=apl inline>⍺</source> and <source lang=apl inline>⍵</source> refer to the arguments of the train. <source lang=apl inline>f</source>, <source lang=apl inline>g</source>, and <source lang=apl inline>h</source> are | + | A train is a series of functions in isolation. An isolated function is either surrounded by parentheses or named. Below, <source lang=apl inline>⍺</source> and <source lang=apl inline>⍵</source> refer to the arguments of the train. <source lang=apl inline>f</source>, <source lang=apl inline>g</source>, and <source lang=apl inline>h</source> are functions (which themselves can be tacit or not), and <source lang=apl inline>A</source> is an array. The arguments are processed by the following rules: |

A 2-train is an ''atop'': | A 2-train is an ''atop'': | ||

Line 53: | Line 53: | ||

|} | |} | ||

− | Only [[dzaima/APL]] allows <source lang=apl inline>(A h)</source>, which it treats as <source lang=apl inline>A∘h</source>.<ref>dzaima/APL: [https://github.com/dzaima/APL/blob/ceea05e25687988ed0980a4abf4b9249b736543f/docs/differences.txt#L19 Differences from Dyalog APL]. Retrieved 09 Jan 2020.</ref> | + | Only [[dzaima/APL]] allows <source lang=apl inline>(A h)</source>, which it treats as <source lang=apl inline>A∘h</source>.<ref>dzaima/APL: [https://github.com/dzaima/APL/blob/ceea05e25687988ed0980a4abf4b9249b736543f/docs/differences.txt#L19 Differences from Dyalog APL]. Retrieved 09 Jan 2020.</ref> See [[Bind]]. |

== Examples == | == 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 [[ | + | 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 [[idiom]]s. |

=== Plus and minus === | === Plus and minus === | ||

Line 75: | Line 75: | ||

=== Fractions === | === Fractions === | ||

− | We can convert decimal numbers to fractions. For example, we can convert <math>2.625</math> to the improper fraction <math>21 | + | We can convert decimal numbers to fractions. For example, we can convert <math>2.625</math> to the improper fraction <math>\tfrac{21}{8}</math> with |

<source lang=apl> | <source lang=apl> | ||

(1∧⊢,÷)2.625 | (1∧⊢,÷)2.625 | ||

21 8 | 21 8 | ||

</source> | </source> | ||

− | Alternatively, we can convert it to the mixed fraction <math>2{5 | + | Alternatively, we can convert it to the mixed fraction <math>2\tfrac{5}{8}</math> with a mixed fraction: |

− | |||

<source lang=apl> | <source lang=apl> | ||

(1∧0 1∘⊤,÷)2.625 | (1∧0 1∘⊤,÷)2.625 | ||

Line 118: | Line 117: | ||

0 0 2 | 0 0 2 | ||

</source> | </source> | ||

− | For a more parallel comparison of the notations, see the [[Comparison_with_traditional_mathematics#Practical_example|comparison with traditional mathematics]]. | + | For a more parallel comparison of the notations, see the [[Comparison_with_traditional_mathematics#Practical_example|comparison with traditional mathematics]]. |

+ | |||

+ | ===The Number of the Beast=== | ||

+ | The following expression for computing the [[wikipedia:666 (number)|number of the Beast]] (and of [[I.P. Sharp]]'s APL-based email system, [[666 BOX]]) nicely illustrates how to read a train. | ||

+ | <source lang=apl> | ||

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

+ | 666 | ||

+ | </source> | ||

+ | First, <source lang=apl inline>((+.×⍨⊢~∘.×)1↓⍳)</source> is supplied with only one argument <source lang=apl inline>17</source> and is thus interpreted monadically. | ||

+ | |||

+ | Second, <source lang=apl inline>(+.×⍨⊢~∘.×⍨)1↓⍳</source> is a 4-train: reading right-to-left, the last 3 components are interpreted as the fork <source lang=apl inline>1↓⍳</source> and the 4-train is interpreted as the atop <source lang=apl inline>(+.×⍨⊢~∘.×⍨)(1↓⍳)</source>. | ||

+ | Similarly, <source lang=apl inline>(+.×⍨⊢~∘.×⍨)</source> is also a 4-train and interpreted as the atop <source lang=apl inline>+.×⍨(⊢~∘.×⍨)</source>. | ||

+ | |||

+ | Thus the accursed train is interpreted as <source lang=apl inline>((+.×⍨(⊢~∘.×⍨))(1↓⍳))17</source>. Having read the train, we now evaluate it monadically. | ||

+ | <source lang=apl> | ||

+ | ((+.×⍨(⊢~∘.×⍨))(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 | ||

+ | </source> | ||

+ | Note that <source lang=apl inline>((⊢⍨∘.×⍨)1↓⍳)</source> is a train computing primes up to the given input. | ||

+ | |||

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

+ | <source lang=apl> | ||

+ | (⍎⊢,⍕∘≢)'((+.×⍨⊢~∘.×⍨)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 | ||

+ | </source> | ||

+ | |||

== External links == | == External links == | ||

− | == Tutorials == | + | === Tutorials === |

− | * APL Cultivation: [https://chat.stackexchange.com/rooms/52405/conversation/lesson-23-transcribing-to-and-reading-trains Transcribing to and reading trains] | + | * Dyalog: [http://help.dyalog.com/16.0/Content/RelNotes14.0/Function%20Trains.htm version 14.0 release notes] |

− | * APLtrainer: [https://www.youtube.com/watch?v=kt4lMZbn-so How to read trains in Dyalog APL code] (video) | + | * [[APL Cultivation]]: [https://chat.stackexchange.com/rooms/52405/conversation/lesson-23-transcribing-to-and-reading-trains Transcribing to and reading trains] |

− | * APLtrainer: [https://www.youtube.com/watch?v=A2LqqBosvY0 Function trains in APL] (video) | + | * [[APLtrainer]]: [https://www.youtube.com/watch?v=kt4lMZbn-so How to read trains in Dyalog APL code] (video) |

− | * Dyalog | + | * [[APLtrainer]]: [https://www.youtube.com/watch?v=A2LqqBosvY0 Function trains in APL] (video) |

+ | * [[Dyalog webinar]]: [https://www.youtube.com/watch?v=Enlh5qwwDuY?t=440 Train Spotting in Dyalog APL] (video) | ||

+ | * [[Dyalog '13]]: [https://www.youtube.com/watch?v=7-93GzDqC08 Train Spotting in Version 14.0] (video) | ||

− | == Documentation == | + | === Documentation === |

* [http://help.dyalog.com/16.0/Content/RelNotes14.0/Function%20Trains.htm Announcement] | * [http://help.dyalog.com/16.0/Content/RelNotes14.0/Function%20Trains.htm Announcement] | ||

* [http://help.dyalog.com/latest/Content/Language/Introduction/Trains.htm Dyalog] | * [http://help.dyalog.com/latest/Content/Language/Introduction/Trains.htm Dyalog] | ||

− | ==References== | + | == References == |

<references/> | <references/> | ||

− | {{APL syntax}} | + | |

+ | {{APL syntax}}[[Category:Tacit programming| ]] |

## Latest revision as of 09:33, 15 May 2020

Tacit functions apply to implicit arguments following a small set of rules. This is in contrast to the explicit use of arguments in dfns (`⍺ ⍵`

) and tradfns (which have named arguments). Known dialects which implement trains are Dyalog APL, dzaima/APL, ngn/apl and NARS2000.

## Contents

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

A 2-train is an *atop*:

```
(g h) ⍵
``` |
```
g ( h ⍵)
``` | |

```
⍺ (g h) ⍵
``` |
```
g (⍺ h ⍵)
``` |

A 3-train is a *fork*:

```
(f g h) ⍵
``` |
```
( f ⍵) g ( h ⍵)
``` | |

```
⍺ (f g h) ⍵
``` |
```
(⍺ f ⍵) g (⍺ h ⍵)
``` |

The *left tine* of a fork can be an array:

```
(A g h)
``` |
```
A g ( h ⍵)
``` | |

```
⍺ (A g h) ⍵
``` |
```
A g (⍺ h ⍵)
``` |

Only dzaima/APL allows `(A h)`

, which it treats as `A∘h`

.^{[1]} See Bind.

## 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 to the improper fraction with

```
(1∧⊢,÷)2.625
21 8
```

Alternatively, we can convert it to the mixed fraction 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 in the direction of another vector :

```
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
```

## External links

### Tutorials

- Dyalog: version 14.0 release notes
- 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

## References

- ↑ dzaima/APL: Differences from Dyalog APL. Retrieved 09 Jan 2020.