Pure (programming language)

Last updated
Pure
Pure lang logo.png
Paradigm Functional, declarative, term rewriting
Designed by Albert Gräf
Developer Albert Gräf
First appeared2008;15 years ago (2008)
Stable release
0.68 / 11 April 2018;4 years ago (2018-04-11)
Typing discipline Strong, dynamic
OS Cross-platform: FreeBSD, Linux, macOS, Windows
License GNU Lesser General Public License
Website agraef.github.io/pure-lang/
Influenced by
Q, Haskell, Lisp, Alice, MATLAB

Pure, successor to the equational language Q, is a dynamically typed, functional programming language based on term rewriting. It has facilities for user-defined operator syntax, macros, arbitrary-precision arithmetic (multiple-precision numbers), and compiling to native code through the LLVM. Pure is free and open-source software distributed (mostly) under the GNU Lesser General Public License version 3 or later.

Contents

Pure comes with an interpreter and debugger, provides automatic memory management, has powerful functional and symbolic programming abilities, and interfaces to libraries in C (e.g., for numerics, low-level protocols, and other such tasks). At the same time, Pure is a small language designed from scratch; its interpreter is not large, and the library modules are written in Pure. The syntax of Pure resembles that of Miranda and Haskell, but it is a free-format language and thus uses explicit delimiters (rather than off-side rule indents) to denote program structure.

The Pure language is a successor of the equational programming language Q, previously created by the same author, Albert Gräf at the University of Mainz, Germany. Relative to Q, it offers some important new features (such as local functions with lexical scoping, efficient vector and matrix support, and the built-in C interface) and programs run much faster as they are compiled just-in-time to native code on the fly. Pure is mostly aimed at mathematical applications and scientific computing currently, but its interactive interpreter environment, the C interface and the growing set of addon modules make it suitable for a variety of other applications, such as artificial intelligence, symbolic computation, and real-time multimedia processing.

Pure plug-ins are available for the Gnumeric spreadsheet and Miller Puckette's Pure Data graphical multimedia software, which make it possible to extend these programs with functions written in the Pure language. Interfaces are also provided as library modules to GNU Octave, OpenCV, OpenGL, the GNU Scientific Library, FAUST, SuperCollider, and liblo (for Open Sound Control (OSC)).

Examples

The Fibonacci numbers (naive version):

fib 0 = 0; fib 1 = 1; fib n = fib (n-2) + fib (n-1) if n>1;

Better (tail-recursive and linear-time) version:

fib n = fibs (0,1) n with   fibs (a,b) n = if n<=0 then a else fibs (b,a+b) (n-1); end;

Compute the first 20 Fibonacci numbers:

map fib (1..20);

An algorithm for the n queens problem which employs a list comprehension to organize the backtracking search:

queens n = search n 1 [] with   search n i p  = [reverse p] if i>n;                 = cat [search n (i+1) ((i,j):p) | j = 1..n; safe (i,j) p];   safe (i,j) p  = ~any (check (i,j)) p;   check (i1,j1) (i2,j2)                 = i1==i2 || j1==j2 || i1+j1==i2+j2 || i1-j1==i2-j2; end;

While Pure uses eager evaluation by default, it also supports lazy data structures such as streams (lazy lists). For instance, David Turner's algorithm [1] for computing the stream of prime numbers by trial division can be expressed in Pure:

primes = sieve (2..inf) with   sieve (p:qs) = p : sieve [q | q = qs; q mod p] &; end;

Use of the & operator turns the tail of the sieve into a thunk to delay its computation. The thunk is evaluated implicitly and then memoized (using call by need evaluation) when the corresponding part of the list is accessed, e.g.:

primes!!(0..99); // yields the first 100 primes

Pure has efficient support for vectors and matrices (similar to that of MATLAB and GNU Octave), including vector and matrix comprehensions. E.g., a Gaussian elimination algorithm with partial pivoting can be implemented in Pure thus:

gauss_elimination x::matrix = p,x when n,m = dim x; p,_,x = foldl step (0..n-1,0,x) (0..m-1) end;  step (p,i,x) j = if max_x==0 then p,i,x else     // updated row permutation and index:     transp i max_i p, i+1,     {// the top rows of the matrix remain unchanged:      x!!(0..i-1,0..m-1);      // the pivot row, divided by the pivot element:      {x!(i,l)/x!(i,j)                 | l=0..m-1};      // subtract suitable multiples of the pivot row:      {{x!(k,l)-x!(k,j)*x!(i,l)/x!(i,j) | k=i+1..n-1; l=0..m-1}} when   n,m = dim x; max_i, max_x = pivot i (col x j);   x = if max_x>0 then swap x i max_i else x; end with   pivot i x = foldl max (0,0) [j,abs (x!j)|j=i..#x-1];   max (i,x) (j,y) = if x<y then j,y else i,x; end;  /* Swap rows i and j of the matrix x. */  swap x i j = x!!(transp i j (0..n-1),0..m-1) when n,m = dim x end;  /* Apply a transposition to a permutation. */  transp i j p = [p!tr k | k=0..#p-1] with tr k = if k==i then j else if k==j then i else k end;  /* Example: */  let x = dmatrix {2,1,-1,8; -3,-1,2,-11; -2,1,2,-3}; x; gauss_elimination x;

As a language based on term rewriting, Pure fully supports symbolic computation with expressions. Here is an example showing the use of local rewriting rules to expand and factor simple arithmetic expressions:

expand = reduce with   (a+b)*c = a*c+b*c;   a*(b+c) = a*b+a*c; end;  factor = reduce with   a*c+b*c = (a+b)*c;   a*b+a*c = a*(b+c); end;  expand ((a+b)*2); // yields a*2+b*2 factor (a*2+b*2); // yields (a+b)*2

Calling C functions from Pure is very easy. E.g., the following imports the puts function from the C library and uses it to print the string "Hello, world!" on the terminal:

externintputs(char*);hello=puts"Hello, world!";hello;

See also

Related Research Articles

<span class="mw-page-title-main">Associative property</span> Property of a mathematical operation

In mathematics, the associative property is a property of some binary operations, which means that rearranging the parentheses in an expression will not change the result. In propositional logic, associativity is a valid rule of replacement for expressions in logical proofs.

<span class="mw-page-title-main">ALGOL</span> Family of programming languages

ALGOL is a family of imperative computer programming languages originally developed in 1958. ALGOL heavily influenced many other languages and was the standard method for algorithm description used by the Association for Computing Machinery (ACM) in textbooks and academic sources for more than thirty years.

<span class="mw-page-title-main">Erlang (programming language)</span> Programming language

Erlang is a general-purpose, concurrent, functional high-level programming language, and a garbage-collected runtime system. The term Erlang is used interchangeably with Erlang/OTP, or Open Telecom Platform (OTP), which consists of the Erlang runtime system, several ready-to-use components (OTP) mainly written in Erlang, and a set of design principles for Erlang programs.

In mathematics, Gaussian elimination, also known as row reduction, is an algorithm for solving systems of linear equations. It consists of a sequence of operations performed on the corresponding matrix of coefficients. This method can also be used to compute the rank of a matrix, the determinant of a square matrix, and the inverse of an invertible matrix. The method is named after Carl Friedrich Gauss (1777–1855) although some special cases of the method—albeit presented without proof—were known to Chinese mathematicians as early as circa 179 AD.

Mercury is a functional logic programming language made for real-world uses. The first version was developed at the University of Melbourne, Computer Science department, by Fergus Henderson, Thomas Conway, and Zoltan Somogyi, under Somogyi's supervision, and released on April 8, 1995.

OCaml is a general-purpose, multi-paradigm programming language which extends the Caml dialect of ML with object-oriented features. OCaml was created in 1996 by Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy, Ascánder Suárez, and others.

In mathematics, a matrix with real entries is positive-definite if the real number is positive for every nonzero real column vector where is the transpose of . More generally, a Hermitian matrix is positive-definite if the real number is positive for every nonzero complex column vector where denotes the conjugate transpose of

<span class="mw-page-title-main">Dynamic programming</span> Problem optimization method

Dynamic programming is both a mathematical optimization method and a computer programming method. The method was developed by Richard Bellman in the 1950s and has found applications in numerous fields, from aerospace engineering to economics.

In linear algebra, the Cholesky decomposition or Cholesky factorization is a decomposition of a Hermitian, positive-definite matrix into the product of a lower triangular matrix and its conjugate transpose, which is useful for efficient numerical solutions, e.g., Monte Carlo simulations. It was discovered by André-Louis Cholesky for real matrices, and posthumously published in 1924. When it is applicable, the Cholesky decomposition is roughly twice as efficient as the LU decomposition for solving systems of linear equations.

In mathematics, and in particular linear algebra, the Moore–Penrose inverse of a matrix is the most widely known generalization of the inverse matrix. It was independently described by E. H. Moore in 1920, Arne Bjerhammar in 1951, and Roger Penrose in 1955. Earlier, Erik Ivar Fredholm had introduced the concept of a pseudoinverse of integral operators in 1903. When referring to a matrix, the term pseudoinverse, without further specification, is often used to indicate the Moore–Penrose inverse. The term generalized inverse is sometimes used as a synonym for pseudoinverse.

In computer science, array programming refers to solutions which allow the application of operations to an entire set of values at once. Such solutions are commonly used in scientific and engineering settings.

Cilk, Cilk++, Cilk Plus and OpenCilk are general-purpose programming languages designed for multithreaded parallel computing. They are based on the C and C++ programming languages, which they extend with constructs to express parallel loops and the fork–join idiom.

Semidefinite programming (SDP) is a subfield of convex optimization concerned with the optimization of a linear objective function over the intersection of the cone of positive semidefinite matrices with an affine space, i.e., a spectrahedron.

In numerical analysis and linear algebra, lower–upper (LU) decomposition or factorization factors a matrix as the product of a lower triangular matrix and an upper triangular matrix. The product sometimes includes a permutation matrix as well. LU decomposition can be viewed as the matrix form of Gaussian elimination. Computers usually solve square systems of linear equations using LU decomposition, and it is also a key step when inverting a matrix or computing the determinant of a matrix. The LU decomposition was introduced by the Polish mathematician Tadeusz Banachiewicz in 1938. It's also referred to as LR decomposition.

In mathematics, the Grothendieck inequality states that there is a universal constant with the following property. If Mij is an n × n matrix with

In mathematics, in the field of control theory, a Sylvester equation is a matrix equation of the form:

This article describes the features in Haskell.

Ateji PX is an object-oriented programming language extension for Java. It is intended to facilliate parallel computing on multi-core processors, GPU, Grid and Cloud.

In mathematical optimization, the revised simplex method is a variant of George Dantzig's simplex method for linear programming.

References

Notes

  1. Turner, David A. SASL language manual. Tech. rept. CS/75/1. Department of Computational Science, University of St. Andrews 1975.