Tacit programming: Difference between revisions

From APL Wiki
Jump to navigation Jump to search
(Created page with "Tacit functions apply to implicit arguments following a small set of rules. This is in contrast to the explicit use of arguments in dfns (<source inline lang=apl>⍺ ⍵</sour...")
 
(21 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Tacit functions apply to implicit arguments following a small set of rules. This is in contrast to the explicit use of arguments in dfns (<source inline lang=apl>⍺ ⍵</source>) and Tradfns (which have named arguments). Known dialects which implement trains are Dyalog APL, dzaima/apl, ngn/apl and NARS2000.
Tacit functions apply to implicit arguments following a small set of rules. This is in contrast to the explicit use of arguments in [[dfns]] (<source inline lang=apl>⍺ ⍵</source>) and [[tradfns]] (which have named arguments). Known dialects which implement trains are [[Dyalog APL]], [[dzaima/APL]], [[ngn/apl]] and [[NARS2000]].


== Primitives ==
== Primitives ==
All primitive functions are tacit. Some APLs allow primitive functions to be named.
All [[primitive functions]] are tacit. Some APLs allow primitive functions to be named.
<source lang=apl>
<source lang=apl>
       plus ← +
       plus ← +
Line 8: Line 8:
       6 times 3 plus 5
       6 times 3 plus 5
48
48
</source>
== Derived functions ==
Functions derived from a monadic operator and an operand, or from a dyadic operator and two operands are tacit functions:
<source lang=apl>
      Sum ← +/
      Sum ⍳10
55
      Dot ← +.×
      3 1 4 dot 2 7 1
17
</source>
== Derived operators ==
A dyadic operator with its right operand forms a tacit monadic operator:
<source lang=apl>
      1(+⍣2)10
12
      Twice ← ⍣2
      1 +Twice 10
12
</source>
</source>


== Trains ==
== Trains ==
A train is a series of functions in isolation. An isolated function is either surrounded by parentheses or named. Arguments are processed by the following rules:
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'':
{|
|<source lang=apl>  (g h) ⍵</source>|| {{←→}} ||<source lang=apl>g (  h ⍵)</source>
|-
|<source lang=apl>⍺ (g h) ⍵</source>|| {{←→}} ||<source lang=apl>g (⍺ h ⍵)</source>
|}
A 3-train is a ''fork'':
{|
|<source lang=apl>  (f g h) ⍵</source>|| {{←→}} ||<source lang=apl>(  f ⍵) g (  h ⍵)</source>
|-
|<source lang=apl>⍺ (f g h) ⍵</source>|| {{←→}} ||<source lang=apl>(⍺ f ⍵) g (⍺ h ⍵)</source>
|}
The ''left tine'' of a fork can be an array:
{|
|<source lang=apl>  (A g h)</source>|| {{←→}} ||<source lang=apl>A g (  h ⍵)</source>
|-
|<source lang=apl>⍺ (A g h) ⍵</source>|| {{←→}} ||<source lang=apl>A g (⍺ h ⍵)</source>
|}
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>
== 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 ===
<source lang=apl>
      (+,-) 2    ⍝ ±2
2 ¯2
      5 (+,-) 2  ⍝ 5±2
7 3
</source>
=== Arithmetic mean ===
<source lang=apl>
<source lang=apl>
  (g h) ⍵ ⬄ g ( h ⍵)
      (+⌿÷≢) ⍳10      ⍝ Mean of the first ten integers
⍺ (g h) ⍵ ⬄ g (⍺ h ⍵)
5.5
      (+⌿÷≢) 5 4⍴⍳4    ⍝ Mean of columns in a matrix
1 2 3 4
</source>
</source>


A 3-train is a ''fork'':
=== Fractions ===
We can convert decimal numbers to fractions. For example, we can convert <math>2.625</math> to the improper fraction <math>21\over 8</math> with
<source lang=apl>
      (1∧⊢,÷)2.625
21 8
</source>
Alternatively, we can convert it to the mixed fraction <math>2{5\over 8}</math> with
A mixed fraction:
<source lang=apl>
      (1∧0 1∘⊤,÷)2.625
2 5 8
</source>
 
=== Is it a palindrome? ===
<source lang=apl>
      (⌽≡⊢)'racecar'
1
      (⌽≡⊢)'racecat'
0
</source>
 
=== Split delimited text ===
<source lang=apl>
<source lang=apl>
  (f g h) ⍵ ⬄ ( f ⍵) g (  h ⍵)
      ','(≠⊆⊢)'comma,delimited,text'
⍺ (f g h) ⍵ ⬄ (⍺ f ⍵) g (⍺ h ⍵)
┌─────┬─────────┬────┐
│comma│delimited│text│
└─────┴─────────┴────┘
      ' '(≠⊆⊢)'space delimited text'
┌─────┬─────────┬────┐
│space│delimited│text│
└─────┴─────────┴────┘
</source>
</source>


The ''left tine'' of a fork (but not an atop) can be an array:
=== 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 <math>\textbf{a}</math> in the direction of another vector <math>\textbf{b}</math>:
:::<math>\textbf{a}_\textbf{b} = (\textbf{a}\cdot\hat{\textbf{b}})\hat{\textbf{b}}</math>
<source lang=apl>
<source lang=apl>
  (A g h) ⍵ ⬄ A g (  h ⍵)
      Root ← *∘÷⍨              ⍝ Nth root
(A g h) ⍵ ⬄ A g (h )
      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
</source>
</source>
For a more parallel comparison of the notations, see the [[Comparison_with_traditional_mathematics#Practical_example|comparison with traditional mathematics]].
== External links ==
== Tutorials ==
* Dyalog: [http://help.dyalog.com/16.0/Content/RelNotes14.0/Function%20Trains.htm version 14.0 release notes]
* 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=kt4lMZbn-so How to read trains in Dyalog APL code] (video)
* 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)


== Expressing algorithms ==
== Documentation ==
One of the major benefits of tacit programming is the ability to convey a short, well-defined idea as an isolated expression ([https://aplwiki.com/wiki/Simple_examples#Tacit_programming example]).  
* [http://help.dyalog.com/16.0/Content/RelNotes14.0/Function%20Trains.htm Announcement]
* [http://help.dyalog.com/latest/Content/Language/Introduction/Trains.htm Dyalog]


{{APL Language}}
==References==
<references/>
{{APL syntax}}

Revision as of 17:10, 7 April 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.

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]

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.

External links

Tutorials

Documentation

References

  1. dzaima/APL: Differences from Dyalog APL. Retrieved 09 Jan 2020.
APL syntax [edit]
General Comparison with traditional mathematicsPrecedenceTacit programming (Train, Hook, Split composition)
Array Numeric literalStringStrand notationObject literalArray notation (design considerations)
Function ArgumentFunction valenceDerived functionDerived operatorNiladic functionMonadic functionDyadic functionAmbivalent functionDefined function (traditional)DfnFunction train
Operator OperandOperator valenceTradopDopDerived operator
Assignment MultipleIndexedSelectiveModified
Other Function axisBracket indexingBranchStatement separatorQuad nameSystem commandUser commandKeywordDot notationFunction-operator overloadingControl structureComment