Tacit programming: Difference between revisions

Content deleted Content added
Functional programming: base case before the recursive case
 
(17 intermediate revisions by 11 users not shown)
Line 1:
{{Short description|Programming paradigm}}
'''Tacit programming''', also called '''point-free style''', is a [[programming paradigm]] in which function definitions do not identify the [[parameter (computer science)|arguments]] (or "points") on which they operate. Instead the definitions merely [[function composition (computer science)|compose]] other functions, among which are [[Combinatory logic|combinators]] that manipulate the arguments. Tacit programming is of theoretical interest, because the strict use of composition results in programs that are well adapted for [[Equational logic|equational]] reasoning.<ref name="cunha2005">{{cite thesis |last1=Cunha |first1=Manuel Alcino Pereira da Cunha (|year=2005) [http|url=https://hdl.handle.net/1822/2869 |title=Point-free Program Calculation |degree=PhD |publisher=[[University of Minho]]}}</ref> It is also the natural style of certainsome [[programming languageslanguage]]s, including [[APL (programming language)|APL]] and its derivatives,<ref>W.{{cite Nevillebook |editor1-last=Holmes, ed|editor1-first=W. (Neville |year=2006) ''|title=Computers and People''}}</ref> and [[concatenative programming language|concatenative languages]] such as [[Forth (programming language)|Forth]]. The lack of argument naming gives point-free style a reputation of being unnecessarilyneedlessly obscure, hence the [[epithet]] "pointless style".<ref name="cunha2005"/>
{{Programming paradigms}}
'''Tacit programming''', also called '''point-free style''', is a [[programming paradigm]] in which function definitions do not identify the [[parameter (computer science)|arguments]] (or "points") on which they operate. Instead the definitions merely [[function composition (computer science)|compose]] other functions, among which are [[Combinatory logic|combinators]] that manipulate the arguments. Tacit programming is of theoretical interest, because the strict use of composition results in programs that are well adapted for [[Equational logic|equational]] reasoning.<ref name="cunha2005">Manuel Alcino Pereira da Cunha (2005) [http://hdl.handle.net/1822/2869 Point-free Program Calculation]</ref> It is also the natural style of certain [[programming languages]], including [[APL (programming language)|APL]] and its derivatives,<ref>W. Neville Holmes, ed. (2006) ''Computers and People''</ref> and [[concatenative programming language|concatenative languages]] such as [[Forth (programming language)|Forth]]. The lack of argument naming gives point-free style a reputation of being unnecessarily obscure, hence the epithet "pointless style".<ref name="cunha2005"/>
 
[[Unix]] [[Command-line interface|scripting]] uses the paradigm with [[Pipeline (Unix)|pipes]].
 
The key idea in tacit programming is to assist in operating at the appropriate level of abstraction.
 
==Examples==
Line 15 ⟶ 12:
return baz(bar(foo(x)))
</syntaxhighlight>
... iscan be written in point-free style as the composition of a sequence of functions, without parameters:<ref>{{cite web | url=http://concatenative.org/wiki/view/Concatenative%20language/Name%20code%20not%20values | title=Name code not values | publisher=Concatenative.org | accessdateaccess-date=13 September 2013}}</ref>
 
<syntaxhighlight lang="python">
Line 25 ⟶ 22:
</syntaxhighlight>
 
For a more complex example, the [[Haskell]] code {{<code|1=>p = ((.) f) . g}}</code> can be translated as:
 
<syntaxhighlight lang="python">
p = partial(compose, partial(compose, f), g)
</syntaxhighlight>
 
===Functional programming===
A simple example (in [[Haskell (programming language)|Haskell]]) is a program which computes the sum of a list of numbers. We can define the sum function recursively using a ''pointed'' style (cf. [[value-level programming|''value''-level programming]]) as:
<syntaxhighlight lang="haskell">sum [] = 0
sum (x:xs) = x + sum xs</syntaxhighlight>
sum [] = 0
</syntaxhighlight>
 
However, using a [[fold (higher-order function)|fold]], wethis can replacebe thisreplaced with:
<syntaxhighlight lang="haskell">
sum xs = foldr (+) 0 xs
Line 54 ⟶ 48:
</syntaxhighlight>
 
The following Haskell-like pseudo-code[[pseudocode]] exposes how to reduce a function definition to its point-free equivalent:
<syntaxhighlight lang="haskell" line highlight="5">
p = \x -> \y -> \z -> f (g x y) z
= \x -> \y -> f (g x y)
Line 75 ⟶ 69:
<syntaxhighlight lang="haskell">
mf = (. map) . (.) . filter
</syntaxhighlight>NoteAs that, as statedsuggested previouslyalready, the points in ''point-free'' refer to the arguments, not to the use of dots; a common misconception.<ref>{{Cite web |url=https://wiki.haskell.org/Pointfree#But_pointfree_has_more_points.21 |title=Pointfree - HaskellWiki|website=wiki.haskellHaskell.org Wiki |access-date=2016-06-05}}</ref>
 
A few programs have been written to automatically convert a Haskell expression to a point-free form.
 
===APL family===
In the language [[J (programming language)|J]], the same sort of point-free code occurs in a function made to compute the average of a list (array) of numbers:
<syntaxhighlight lang=j>avg=: +/ % #</syntaxhighlight>
<code>+/</code> sums the items of the array by mapping (<code>/</code>) summation (<code>+</code>) to the array. <code>%</code> divides the sum by the number of elements (<code>#</code>) in the array.
Line 124 ⟶ 118:
===Pipelines===
====Unix pipeline====
{{mainFurther|Pipeline (Unix)}}
 
In Unix scripting the functions are computer programs which receive data from [[Standard streams|standard input]] and send the results to [[Standard streams|standard output]]. For example,
 
<syntaxhighlight lang="bash">
sort | uniq -c | sort -rn
</syntaxhighlight>
is a tacit or point-free composition which returns the counts of its arguments and the arguments, in the order of decreasing counts. The 'sort' and 'uniq' are the functions, the '-c' and '-rn' control the functions, but the arguments are not mentioned. The pipe '|' is the composition operator.
 
is a tacit or point-free composition which returns the counts of its arguments and the arguments, in the order of decreasing counts. The '{{mono|sort'}} and '{{mono|uniq'}} are the functions, the '{{Code|-c'}} and '{{Code|-rn'}} control the functions, but the arguments are not mentioned. The pipe '<Code>|'</code> is the composition operator.
Due to the way pipelines work, it is only normally possible to pass one "argument" at a time in the form of a pair of standard input/output stream. Although extra [[file descriptor]]s can be opened from [[named pipe]]s, this no longer constitutes a point-free style.
 
Due to the way pipelines work, it is only normally possible only to pass one "''argument"'' at a time in the form of a pair of standard [[input/output]] stream. Although extra [[file descriptor]]s can be opened from [[named pipe]]s, this no longer constitutes a point-free style.
 
====jq====
 
[[jq (programming language)|jq]] is a [[JSON]]-oriented programming language in which the <code>|</code> symbol is used to connect filters to form a pipeline in a familiar way. For example:
the '|' symbol is used to connect filters to form a pipeline
in a familiar way. For example:
 
[1,2] | add
 
evaluates to 3. (Yes, the JSON array is a jq filter that evaluates to an array.)
evaluates to 3.
 
Although similar to Unix pipelines, jq pipelines allow the incoming data to be sent to more than one recipient on the RHS of the <code>|</code> as though in parallel. For example, the program <code>add/length</code> will compute the average of the numbers in an array, so that:
incoming data to be sent to more than one recipient on the
RHS of the '|' as though in parallel. For example, the program `add/length`
will compute the average of the numbers in an array, so that:
 
[1,2] | add/length
Line 160 ⟶ 148:
evaluates to [2,3,1.5]
 
A dot ('<code>.'</code>) can be used to define an attachment point on the RHS, e.g.:
 
1 | [., .]
Line 170 ⟶ 158:
2 | pow(.; .)
 
evaluates to 4 since <code>pow(x;y)</code> is x to the power y.
 
=====FibonnaciFibonacci sequence=====
 
A tacit jq program for generating the FibonnaciFibonacci sequence would be:
 
[0,1] | recurse( [last, add] ) | first
 
Here, <code>[0,1]</code> is the initial pair to be taken as the first two items
in the FibonnaciFibonacci sequence. (The pair <code>[1,1]</code> could likewise be used for
the variant definition.)
 
The alphabetic tokens are built-in filters: `first` and `last`
emit the first and last elements of their input arrays respectively;
and `<code>recurse(f)`</code> applies a filter, f, to its input recursively.
 
jq also allows new filters to be defined in a tacit style, e.g.:
Line 193 ⟶ 181:
 
In the section on Python in this article, the following Python definition is considered:
<syntaxhighlight lang="python">
```
def example(x):
return baz(bar(foo(x)))
</syntaxhighlight>
```
In point-free style, this could be written in Python as:
example = compose(foo, bar, baz)
 
In jq, the equivalent point-free definitionstyle, wouldthis can be written in Python as:
 
example = compose(foo, bar, baz)
 
In jq, the equivalent point-free definition would be:
def example: foo | bar | baz;
 
Line 214 ⟶ 203:
 
==External links==
* [https://function-level.github.io/ From Function-Level Programming to Pointfree Style]
* [http://portal.acm.org/citation.cfm?id=114065&dl=GUIDE&coll=GUIDE Pure Functions in APL and J] How to use tacit programming in any APL-like language
* [http://dirkgerrits.com/publications/john-backus.pdf#section.8 Closed applicative languages 1971 - 1976 ff], in John W. Backus (Publications)
 
{{Programming paradigms navbox}}
 
[[Category:Programming paradigms]]
[[Category:Programming language comparisons]]
<!-- Hidden categories below -->
[[Category:Articles with example Haskell code]]
[[Category:Articles with example Python (programming language) code]]