Tacit programming, also called point-free style, is a
programming paradigm
Programming paradigms are a way to classify programming languages based on their features. Languages can be classified into multiple paradigms.
Some paradigms are concerned mainly with implications for the execution model of the language, s ...
in which function definitions do not identify the
arguments
An argument is a statement or group of statements called premises intended to determine the degree of truth or acceptability of another statement called conclusion. Arguments can be studied from three main perspectives: the logical, the dialectic ...
(or "points") on which they operate. Instead the definitions merely
compose other functions, among which are
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 reasoning.
[Manuel Alcino Pereira da Cunha (2005]
Point-free Program Calculation
/ref> It is also the natural style of certain programming languages
A programming language is a system of notation for writing computer program, computer programs. Most programming languages are text-based formal languages, but they may also be visual programming language, graphical. They are a kind of computer ...
, including APL and its derivatives, and concatenative languages
A concatenative programming language is a point-free computer programming language in which all expressions denote functions, and the juxtaposition of expressions denotes function composition. Concatenative programming replaces function appli ...
such as Forth
Forth or FORTH may refer to:
Arts and entertainment
* ''forth'' magazine, an Internet magazine
* ''Forth'' (album), by The Verve, 2008
* ''Forth'', a 2011 album by Proto-Kaw
* Radio Forth, a group of independent local radio stations in Scotla ...
. The lack of argument naming gives point-free style a reputation of being unnecessarily obscure, hence the epithet "pointless style".
Unix
Unix (; trademarked as UNIX) is a family of multitasking, multiuser computer operating systems that derive from the original AT&T Unix, whose development started in 1969 at the Bell Labs research center by Ken Thompson, Dennis Ritchie, a ...
scripting
Script may refer to:
Writing systems
* Script, a distinctive writing system, based on a repertoire of specific elements or symbols, or that repertoire
* Script (styles of handwriting)
** Script typeface, a typeface with characteristics of handw ...
uses the paradigm with pipes
Pipe(s), PIPE(S) or piping may refer to:
Objects
* Pipe (fluid conveyance), a hollow cylinder following certain dimension rules
** Piping, the use of pipes in industry
* Smoking pipe
** Tobacco pipe
* Half-pipe and quarter pipe, semi-circul ...
.
The key idea in tacit programming is to assist in operating at the appropriate level of abstraction.
Examples
Python
Tacit programming can be illustrated with the following Python code. A sequence of operations such as the following:
def example(x):
return baz(bar(foo(x)))
... is written in point-free style as the composition of a sequence of functions, without parameters:
from functools import partial, reduce
def compose(*fns):
return partial(reduce, lambda v, fn: fn(v), fns)
example = compose(foo, bar, baz)
For a more complex example, the Haskell code can be translated as:
p = partial(compose, partial(compose, f), g)
Functional programming
A simple example (in Haskell
Haskell () is a general-purpose, statically-typed, purely functional programming language with type inference and lazy evaluation. Designed for teaching, research and industrial applications, Haskell has pioneered a number of programming lan ...
) 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) as:
sum (x:xs) = x + sum xs
sum [] = 0
However, using a fold (higher-order function), fold we can replace this with:
sum xs = foldr (+) 0 xs
And then the argument is not needed, so this simplifies to
sum = foldr (+) 0
which is point-free.
Another example uses function composition
In mathematics, function composition is an operation that takes two functions and , and produces a function such that . In this operation, the function is applied to the result of applying the function to . That is, the functions and ...
:
p x y z = f (g x y) z
The following Haskell-like pseudo-code exposes how to reduce a function definition to its point-free equivalent:
p = \x -> \y -> \z -> f (g x y) z
= \x -> \y -> f (g x y)
= \x -> \y -> (f . (g x)) y
= \x -> f . (g x)
(* Here the infix compose operator "." is used as a curried function. *)
= \x -> ((.) f) (g x)
= \x -> (((.) f) . g) x
p = ((.) f) . g
Finally, to see a complex example imagine a map filter program which takes a list, applies a function to it, and then filters the elements based on a criterion
mf criteria operator list = filter criteria (map operator list)
It can be expressed point-free as
mf = (. map) . (.) . filter
Note that, as stated previously, the points in 'point-free' refer to the arguments, not to the use of dots; a common misconception.
A few programs have been written to automatically convert a Haskell expression to a point-free form.
APL family
In J, the same sort of point-free code occurs in a function made to compute the average of a list (array) of numbers:
avg=: +/ % #
+/
sums the items of the array by mapping (/
) summation (+
) to the array. %
divides the sum by the number of elements (#
) in the array.
Euler's formula
Euler's formula, named after Leonhard Euler, is a mathematical formula in complex analysis that establishes the fundamental relationship between the trigonometric functions and the complex exponential function. Euler's formula states that for ...
expressed tacitly:
cos =: 2 o. ]
sin =: 1 o. ]
Euler =: ^@j. = cos j. sin
(j.
is a primitive function whose monadic definition is 0j1
times x and whose dyadic definition is x+0j1×y
.) The same tacit computations expressed in APL_(programming_language)#Dyalog_APL, Dyalog APL:
avg ← +⌿ ÷ ≢
cos ← 2 ○ ⊢
sin ← 1 ○ ⊢
EulerCalc← cos + 0j1 × sin ⍝ 0j1 is what's usually written as i
EulerDirect← *0J1×⊢ ⍝ Same as ¯12○⊢
⍝ Do the 2 methods produce the same result?
EulerCheck← EulerDirect=EulerCalc
EulerCheck ¯1 1 2 3
1 1 1 1
⍝ Yes, so far so good!
Stack-based
In stack-oriented programming language
Stack-oriented programming, is a programming paradigm which relies on a stack machine model for passing parameters. Stack-oriented languages operate on one or more stacks, each of which may serve a different purpose. Programming constructs in ...
s (and concatenative ones, most of which are stack based), point-free methods are commonly used. For example, a procedure to compute the Fibonacci number
In mathematics, the Fibonacci numbers, commonly denoted , form a integer sequence, sequence, the Fibonacci sequence, in which each number is the sum of the two preceding ones. The sequence commonly starts from 0 and 1, although some authors start ...
s might look like the following in PostScript
PostScript (PS) is a page description language in the electronic publishing and desktop publishing realm. It is a dynamically typed, concatenative programming language. It was created at Adobe Systems by John Warnock, Charles Geschke, ...
:
/fib
def
Pipelines
Unix pipeline
In Unix scripting the functions are computer programs which receive data from standard input
In computer programming, standard streams are interconnected input and output communication channels between a computer program and its environment when it begins execution. The three input/output (I/O) connections are called standard input (stdin ...
and send the results to standard output
In computer programming, standard streams are interconnected input and output communication channels between a computer program and its environment when it begins execution. The three input/output (I/O) connections are called standard input (stdin ...
. For example,
sort , uniq -c , sort -rn
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.
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
In Unix and Unix-like computer operating systems, a file descriptor (FD, less frequently fildes) is a process-unique identifier ( handle) for a file or other input/output resource, such as a pipe or network socket.
File descriptors typically ...
s can be opened from named pipe
In computing, a named pipe (also known as a FIFO for its behavior) is an extension to the traditional pipe concept on Unix and Unix-like systems, and is one of the methods of inter-process communication (IPC). The concept is also found in OS/ ...
s, this no longer constitutes a point-free style.
jq
jq is a JSON-oriented programming language in which
the ', ' symbol is used to connect filters to form a pipeline
in a familiar way. For example:
,2, add
evaluates to 3. (Yes, the JSON array is a jq filter that evaluates to an array.)
Although similar to Unix pipelines, jq pipelines allow the
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:
,2, add/length
evaluates to 1.5
Similarly:
,2, ength, add, add/length
evaluates to ,3,1.5
A dot ('.') can be used to define an attachment point on the RHS, e.g.:
1 , , .
The comma is a punctuation mark that appears in several variants in different languages. It has the same shape as an apostrophe or single closing quotation mark () in many typefaces, but it differs from them in being placed on the baseline o ...
evaluates to ,1
and similarly:
2 , pow(.; .)
evaluates to 4 since pow(x;y) is x to the power y.
=Fibonnaci sequence
=
A tacit jq program for generating the Fibonnaci sequence would be:
,1, recurse( ast, add) , first
Here, ,1is the initial pair to be taken as the first two items
in the Fibonnaci sequence. (The pair ,1could 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 `recurse(f)` applies a filter, f, to its input recursively.
jq also allows new filters to be defined in a tacit style, e.g.:
def fib: ,1, recurse( ast, add) , first;
=Composition of unary functions
=
In the section on Python in this article, the following Python definition is considered:
def example(x):
return baz(bar(foo(x)))
In point-free style, this could be written in Python as:
example = compose(foo, bar, baz)
In jq, the equivalent point-free definition would be:
def example: foo , bar , baz;
See also
* Combinatory logic
Combinatory logic is a notation to eliminate the need for quantified variables in mathematical logic. It was introduced by Moses Schönfinkel and Haskell Curry, and has more recently been used in computer science as a theoretical model of compu ...
* Concatenative programming language
A concatenative programming language is a point-free computer programming language in which all expressions denote functions, and the juxtaposition of expressions denotes function composition. Concatenative programming replaces function appli ...
* Function-level programming
* Joy (programming language)
The Joy programming language in computer science is a purely functional programming language that was produced by Manfred von Thun of La Trobe University in Melbourne, Australia. Joy is based on composition of functions rather than lambda calcu ...
, modern highly tacit language
References
{{Reflist
External links
Pure Functions in APL and J
How to use tacit programming in any APL-like language
Closed applicative languages 1971 - 1976 ff
in John W. Backus (Publications)
Programming paradigms