52

I've read "what-is-turing-complete" and the wikipedia page, but I'm less interested in a formal proof than in the practical implications of requirements for being Turing Complete.

What I'm actually trying to decide is if the toy language I've just designed could be used as a general-purpose language. I know I can prove it is if I can write a Turing machine with it. But I don't want to go through that exercise until I'm fairly certain of success.

Is there a minimum set of features without which Turing Completeness is impossible? Is there a set of features which virtually guarantees completeness?

(My guess is that conditional branching and a readable/writeable memory store will get me most of the way there)


EDIT:

I think I've gone off on a tangent by saying "Turing Complete". I'm trying to guess with reasonable confidence that a newly invented language with a certain feature set (or alternately, a VM with a certain instruction set) would be able to compute anything worth computing. I know that proving you can build a Turing machine with it is one way, but not the only way.

What I was hoping for was a set of guidelines like: "if a language can do X,Y,and Z, it can probably do anything".

AShelly
  • 34,686
  • 15
  • 91
  • 152
  • 3
    Why would any programmer care? it's not as if turing-completeness alone has any practical relevance for the usability of a programming language. –  Jan 16 '09 at 00:54
  • 1
    Your guess will get you all the way if you also include some kind of iteration or recursion. :-) –  Jan 16 '09 at 01:22
  • 8
    @Kent: Phah, who needs iteration or recursion when they've got *conditional branching*? IF and GOTO, baby! – Thomas Apr 04 '10 at 15:54

13 Answers13

47

You need some form of dynamic allocation construct (malloc ornew or cons will do) and either recursive functions or some other way of writing an infinite loop. If you have those and can do anything at all interesting, you're almost certainly Turing-complete.

The lambda calculus is equivalent in power to a Turing machine, and if you implement lambda calculus it is actually pretty fun writing lambda calculus programs. Way more fun than writing program for a Turing machine!

The only practical implication of Turing-completeness I'm aware of is that you can write programs that don't terminate. I've used a couple of special-purpose languages that guarantee termination and therefore are not Turing-complete. Sometimes it is useful to give up the extra expressive power in exchange for guaranteed termination.

umlcat
  • 4,091
  • 3
  • 19
  • 29
Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • 4
    This is really not true about needing dynamic allocation. The definitive thought-experiment Turing machine just has an array of bits. One sufficiently large indexable array is enough. Obviously on top of that you can write dynamic allocation within the language if you want. – poolie Sep 28 '10 at 23:53
  • 3
    @poolie - technically the array needs to be infinite for the true definition of 'Turing Completeness'. Ability to dynamically allocate storage sort of approximates this property. – ConcernedOfTunbridgeWells Sep 30 '10 at 13:56
  • 2
    @concerned, If you're going to insist on "infinite", then you need the ability to malloc infinite memory too, and no practical system actually allows that. But we still say that they are, for practical purposes, Turing-complete, as long as there is enough space to do the computation. That's why I said "sufficiently large". – poolie Oct 01 '10 at 01:20
  • 3
    With `malloc`, the fact that memory is limited is not part of the language anymore. Memory is limited only by the implementation/target computer pair. That's an important difference. See https://esolangs.org/wiki/Bounded-storage_machine –  Aug 29 '15 at 18:34
  • 1
    @poolie I feel that memory allocation is more of an implementation detail. You could think of memory in your machine as being "allocated" when a cell that has not been previously moved to before is moved to, but the theoretical machine would have an *infinite* tape rather than just an *unbounded* one. The difference lies in implementation; you cannot have infinite memory so you must do some dynamic allocation. – Challenger5 Dec 18 '16 at 00:59
32

'Turing Completeness' describes the property of being able to express any arbitrary algorithmic computation, which was the point of Turing's Machine in the first place. A language or logical system can be described as 'Turing Complete' if it has this property. From a practical perspective all general purpose programming languages - and a surprisingly large number of special purpose ones - can do this for a suitably loose definition (see below).

However, a strict definition of Turing Completeness implies infinite storage capacity, which is of course not physically possible. Given this, no physical machine can possibly be Turing Complete, but this constraint is usually relaxed (at least informally) when ascribing Turing Completeness to a programming language. One trivial test of Turing Completeness for a language is whether the language can be used to implement a Turing Machine simulator.

An example of a widespread system that is not Turing Complete is Relational Algebra, the theoretical basis behind SQL as described in Codd's paper A relational model for large shared data banks. Relational Algebra has the property of Godel Completeness, which means that it can express any computation that can be defined in terms of first-order predicate calculus (i.e. ordinary logical expressions). However, it is not Turing-Complete as it cannot express an arbitrary algorithmic computation.

Note that most if not all all practical SQL dialects extend the pure relational model with procedural constructs to the extent that they are Turing Complete by the definition as normally applied to programming languages. However, an individual SQL query by and large is not.

Some more egregious examples of Turing Complete domain-specific languages are TeX and sendmail.cf,. In the latter case there is actually a famous-ish example of someone using sendmail.cf to implement a universal Turing Machine simulator.

ConcernedOfTunbridgeWells
  • 64,444
  • 15
  • 143
  • 197
  • 3
    Lots of good information here. Don't know why your answer was at -1 when I came to it. – harms Jan 16 '09 at 18:34
  • The first two sentences of your second paragraph are highly misleading. The concept of Turing completeness only applies to programming languages, not to physical machines, so your statement "no physical machine can possibly be Turing Complete" is vacuous. And no constraint is "usually relaxed (at least informally) when ascribing Turing Completeness to a programming language." A system of effectively computable rules R (like a programming language) is Turing complete if, for any positive integers N and m and Turing program P for an m-state Turing machine, there exists an integer T ... – tparker Aug 07 '17 at 19:29
  • 1
    ... such that stepping through R T different times yields the state of the Turing tape after N Turing steps. This definition does not require "infinite storage capacity" for the physical computer running the code, nor indeed does it make any reference at all to such a physical computer. Turing-completeness is a purely mathematical concept: the programming language C is "just as Turing-complete" when run on ENIAC (I know, ENIAC never actually ran a C program) as when run on a modern supercomputer. Turing's genius was to define the power of a programming language in a way that had ... – tparker Aug 07 '17 at 19:36
  • ... *nothing* to do with the power of the physical machine that runs it in the real world. No constraints need to be relaxed. – tparker Aug 07 '17 at 19:37
11

If you can write a Brainf$&# interpreter in your language, it is Turing-complete. LOLCODE was proved to be Turing-complete in exactly this way.

Luke Woodward
  • 63,336
  • 16
  • 89
  • 104
10

Examples of languages that are not Turing-complete frequently have bounded loops, like:

for i=1 to N {...}

but lack unbounded loops which check a more general condition, like:

while bool_expr {...}

If all possible looping constructs are bounded, your program is guaranteed to terminate. And, although an unconditional termination guarantee is potentially useful, it is also an indication that the language is not Turing-complete.

Note also that nailing down all possible looping constructs can be difficult; e.g., I'm pretty sure C++ templates were not intended to be Turing-complete...

comingstorm
  • 25,557
  • 3
  • 43
  • 67
7

I'm not sure if there's a "minimum set of features", but to prove that a language is Turing complete, you only have to prove that it can emulate another Turing complete system (not necessarily a Turing machine), as long as the other system is known to be Turing complete. http://en.wikipedia.org/wiki/Turing_complete#Examples has a whole list of Turing complete systems. Some of them are simpler than Turing machines.

Nate879
  • 383
  • 1
  • 3
  • 8
5

Brainfuck is Turing complete, and has only loop structures and memory incrementation/decrementation so this is enough.

On the other hand there is no way to modify any value in the lambda calculus, but it is Turing complete, so it it is clearly possible to do it without mutable memory.

Most likely you program has nothing to do with the lambda calculus though, so for a practical answer the minimum must be

  1. A way to write to a variable
  2. A way to read to a variable
  3. A form of conditional goto (if statement, while loop, etc)
tomjen
  • 3,779
  • 3
  • 29
  • 35
3

I'd like to add one caveat to what Norman Ramsey said: a Turing machine has infinite memory and hence programming languages that are considered to be Turing complete are only so under the assumption that memory is also infinite.

Christian Lindig
  • 1,216
  • 1
  • 9
  • 24
2

You can try emulating an OISC (One Instruction-Set Computer). If you can emulate one of the instructions there, then since those single instruction can be used to compose a Turing Complete machine, then you have proven that your language must be Turing Complete as well.

Lie Ryan
  • 62,238
  • 13
  • 100
  • 144
2

I cannot remember seeing anything like minimum features for Turing Completeness. However, if your language supports loops and conditional branches, the chances that it is Turing complete is good. However, the only way to prove it is still to similate a Turing Machine or another Turing Complete language.

PolyThinker
  • 5,152
  • 21
  • 22
1

Any language capable of non-termination is pretty much Turing Complete. You can make a language non-terminating capable by giving it unbounded looping structures (Like While loops or a Goto that can reach itself again), or by giving it general recursion (by letting a function call itself without restriction.)

Once you are turing complete, you can do things like interpret other Turing Complete languages, including your own.

The real question is "what good is it?" If your language is going to be used in a specific domain to solve specific problems, it may be better to find a way to phrase the solutions in a language that is not Turing Complete, and thus guaranteed to give an answer.

You can always add Turing Completeness by writing "Do this, that, or whatever; but do it with the result provided by X" in any other Turing Complete language, where X is provided by a non-Turing complete language.

Of course, if you want to only use one language, it had probably better be Turing Complete...

Retra
  • 11
  • 1
1

Is there a minimum set of features without which Turing Completeness is impossible? Is there a set of features which virtually guarantees completeness?

Yes, you need to have flow of control conditional on data: what is often expressed as if. For example a +-*/ pocket calculator is not Turing-complete, since there is no way to express conditionals.

You also need to be able to express a jump back to an earlier point in the program, on top of which you could implement a loop. For example BPF, which forbids backwards jumps to guarantee the program will terminate, is also not Turing complete.

You need some storage that is both readable and writable and arbitrarily large. For example, a language that has only two 32-bit variables is limited in what it can compute. You have many options for how the storage is structured: memory addressed by pointers, arrays, stacks, cons cells, pure data structures, etc.

On top of these you can build every other programming language: it may not be easy or fast, but it is enough.

poolie
  • 9,289
  • 1
  • 47
  • 74
1

If you can implement a Turing machine (as far as they can be implemented, as they're mathematical constructs with unlimited memory [the tape size is infinte]) then you can be sure it's Turing complete.

Some indications:

  • You can check memory and manipulate it based on the current value as well as using it to control program flow.
  • That memory can be allocated memory, strings which you're able to append to, a stack which you can allocate memory on through recursion etc.
  • Program flow can be through iteration or through selection based recursion.
-5

...than in the practical implications of being Turing Complete.

I doubt there are any practical implications of being Turing complete.

If you look at some of the examples of Turing complete machines, e.g., the original Turing machine, you'll see that the are so far from being useful for real computations that the concept must only be of theoretical interest.

David Norman
  • 19,396
  • 12
  • 64
  • 54
  • 2
    I recommend studying this topic a bit further. Turing completeness does have some very real practical implications. If you have a language that is not Turing complete then it is very weird and you will not be able to solve problems that the vast majority of other programming languages can. – BobbyShaftoe Jan 16 '09 at 00:14
  • I certainly think that it's important for a language to be Turing complete. I just isn't practical, since any language that is designed to be useful for real work will end up Turing complete. – David Norman Jan 16 '09 at 00:54
  • 2
    this answer should be _the_ answer to this question, not voted down. the impracticality of non-turing-complete languages does not make turing-complete languages inherently practical! –  Jan 16 '09 at 00:55
  • I didn't vote it down, but it's not _the_ answer to _my_ question. I should have said "the implications Turing completeness has on the required feature set of a language". And I guess I could have substituted "ability to act as universal machine" for "Turing completeness". – AShelly Jan 16 '09 at 01:15
  • Turing completeness is a sign that the language is on par with other languages when it comes to expressiveness. Of course it doesn't imply much practically as a language "useful for real work" will probably be turing complete. However, the answer doesn't relate to the question, it got my down vote. –  Jan 16 '09 at 01:26
  • 1
    turing completeness has _nothing_ to do whatsoever with expressiveness. what are you people smoking? –  Jan 16 '09 at 21:37
  • 3
    Shader languages and regular expressions are both examples of languages that are not Turing complete. Both are very expressive and highly practical. – Jasper Bekkers Jan 19 '09 at 13:16
  • @Jasper, that's exactly right. Though I believe modern shader languages actually are Turing-complete, though older ones weren't. http://en.wikipedia.org/wiki/Shading_language – poolie Sep 29 '10 at 00:02