While I agree that it is a bit of a misnomer to say that anything is possible in a turing complete language from a feasibility stand point, I think this response falls back to a common thought process that technical minded people go through - literal answers. Of course it is possible to do it, it may just be incredibly difficult. When most people ask if they can do X in Foo, they are usually asking if it is a good idea to do X in Foo. Should the person being asked tell them no even if it is a possibility that is not easy?
I agree. The OP blog post is mistaking. I think the real language misuse is on the behalf of Person A. When asking whether you "can do something in the Foo programming language" this could be a question of theoretical universality or a question of practicality. If it's one of practicality, then it has nothing to do with Turing universality. If it's theoretical, as in "is Foo expressive enough to describe such and such a computation at all", then universality matters.
Also, from a computationalist's perspective in Philosophy, Turing completeness literally does mean being able to do anything that a single-taped Turing machine can do (such as writing a GUI or writing to a screen). If you a priori disconnect your Turing machine from the screen, effectively eliminating the logical possibility to print to it (or, similarly, you use some pared down language where specific functionality is intentionally left out) then it makes no sense at all to bring Turing completeness into it. It seems like the OP either rejects the Extended Church Turing thesis, or mistakenly thinks that other people lump all possible hardware limitations into Turing completeness. If a language is resource bounded, then it is only Turing complete w.r.t. a Turing machine that has the same resource bounds.
> anything that a single-taped Turing machine can do (such as writing a GUI or writing to a screen).
Wait, those are the things a Turing machine CANNOT do! A Turing machine has no input or output, the computation it defines is purely a function of what's on its tape before and after its work (when it halts).
> If you a priori disconnect your Turing machine from the screen
Again this makes no sense, the ('a priori') defintion of a Turing machine does not include a screen, so there's nothing to disconnect. It's really just the tape.
And no, it's quite a stretch to claim that person A could be talking about universality, the blog post says he was asking about GUIs so that's squarely a practical question.
> or [...] thinks that other people lump all possible hardware limitations into Turing completeness.
I have no idea how you arrive at this from the blog post.
Turing machine is a tape + some functions that modify this tape.
If you connect screen to the tape so it shows part of the content of the tape in some manner - do this mean that Turing machine can print on the screen, or not?
Bad analogy:
I can write, but I don't have pen and paper bundled from my birth. I understand being able to print to screen as being able to put information in a form that allows screen to show it.
Otherways no programming language can print to screen, because programming languages are software, and screen is hardware.
These are just resource limitations. I already addressed that. If you start out with something where a resource limitation prevents you from doing X, then any kind of statement about Turing completeness inherently only draws a comparison with a Turing machine that has the same resource limitation keeping it from doing X. It doesn't matter if this is sending RGB data to a monitor (which some languages cannot do unless augmented with certain hardware) or computing Kolmogorov complexity (which no language can do in general). A human plus paper and pencil is a different computation than a human without paper and pencil, just in terms of hardware and memory.
It also seems like some of you are not computationalists. Anything physical is just the result of a computation, whether you are talking about the chemistry of producing colors on a monitor or adding two numbers by sending electrons through circuits of transistors. The ECT thesis says that anything which can be computed in the real world can be computed efficiently by some Turing machine. This includes anything a brain can do (aided by pen and paper or unaided) and certainly includes anything your graphics driver can do. If Java can't do something that Java + Graphics Card + OS can do, then Java has a more serious resource bound, and all claims of Java's Turing completeness inherently include this resource bound. You guys might like some sections of this research paper: (http://www.scottaaronson.com/papers/philos.pdf).
Strictly speaking no GUI can be written using only a programming language like perl, java, tcl...
I/O has nothing to do in the discussion comparing Turing Complete vs. "supporting some language feature in a way that makes it practical for humans to use it.".
What is a programming language other than a language for creating instructions for moving pieces of matter around? You could do this with Java if you give it the same physical resources that the current graphics pipelines have. That stuff isn't exposed to Java and would be pretty cumbersome to manipulate with Java, but it can still in principle be done.
OP here. I was going to write just this, I didn't do it until now because I was on my phone and I wanted a real keyboard to answer. So thanks for doing it for me.
As a side note, I'll add that "person A"s are people I know IRL and this troll (let's call it what it is) aimed at them, not HN audience ;-).
Agreed (also agree with another post at this level).
It seems like a clever "nit" to pick but the only thing you need to add to "turing complete" is "able to address memory in a reasonable way" (or "not sandboxed from memory") and you get everything the author is complaining about and you're back to square one (i.e. the language is "turing complete and has memory access".
How do I print? I stick stuff in the right places in memory and set the program counter. How do I draw graphics? I stick stuff in the right place in memory and set the program counter.
Ahhhh no I disagree. I think this is one of those 140 char limit short sound bite problems that often makes the people listening hard to understand.
Turing Completeness is about computability, but also implies the functions in that class are able to simulate each other. So "theoretically", you COULD write an interpreter in Brainfuck without "," and "." that simulates language L by doing output using some other means, or representing it differently besides printing it out onto the screen. All it has to do is to leave an output state on a Turing Machine.
Now the question, when people talk about "Foo is Turing complete so you can do everything.", is this really what they mean? Probably not, most of them only say this half-jokingly. It's theoretically possible, it's just very unpractical in reality. I'm nonetheless equally annoyed by the term "general purpose language" for the reasons pointed in the post tho.
Turing completeness deals with computability, not with the practicalities of IO and so on.
To say that something is Turing complete simply means that you could implement a universal Turing machine, which can then run any other Turing machine as its program, and so can compute anything that is in theory (without any constraints on time and space) computable.
I understand the authors aggravation with people throwing around the sentence 'x is Turing complete, so you can do anything in x' without any appreciation of the disconnect between the theoretical and the practical sides of this, but I think that it's use is more in jest than serious and that the author should possibly grow a sense of humor.
Typical use:
A: can you do 'x' in Perl
B: Perl is Turing complete, of course you can do 'x'.
Shows that person 'B' has a sense of humor and/or wants to get rid of the questioner without having to answer the question, not that they're clueless about the practicalities of this statement.
It's analogous to 'google it', 'rtfm' or any one of another 100 ways in which people try to show their superiority over others or try to create an 'in' and and 'out' group. Think of it as just another meme and move on.
No, I've flagged it because this 'Turing Completeness Bullshit' is not bullshit, but the article is. Turing completeness actually has a use and railing against the people that use it in a manner that it was never intended to be used in is a total waste of time.
Flagging is not for disagreement, it's for spam, off-topic posts, and link-jacking. You flagged this article because HN doesn't have a down vote for articles, but what you are really doing is messing up the spam filters by training them that words like "Turing" are associated with articles that may get flagged.
Please do not flag articles simply because you think they are wrong. Express your disagreement and move on.
The two statements aren't really analogous. Yours is simply incorrect, while the one in the article is a correct (factual) response that's just not helpful.
Aye, I always think of the halting problem as "if the program is still running, you can't necessarily know if it will ever halt." If you see a program halt, after a millisecond or after 10 years, then you've obviously proven whether or not it halts.
Also, while the halting problem doesn't necessarily say anything about bugs, there is a more general theorem that essentially says that you can't know in general if a program enjoys any non-trivial property (e.g. it prints a "1" at some point, it accesses the network, or it halts). I can't recall the name of the theorem, but the intuitive proof is similar to the halting problem's. This theorem does seem to hint that programs can't be proven to be bug-free in general.
There are several classes of programs that can be proved to halt. Any non-recursive program without a loop halts. In addition to that, our research group in grad school showed that some looping programs can also be proved to halt as long as they are marked with loop termination clauses that can be proved to hold for the program in question. Look to Ohio State RSRG for more info.
Turing completeness concerns itself with the ability of a computer to solve problems that are computable. Modern computers, however, are almost entirely purposed towards interacting with humans and processing data.
Mathematically these "problems" are isomorphic, but the real world concerns itself with issues like correctness, robustness, performance, efficiency, cost, scalability, etc.
The idea of turing completeness compares a 100% perfect program against another 100% perfect program. It does not concern itself at all with efficiency, which is horrific in and of itself, but worse yet it does not concern itself with the difficulty of creating and maintaining the program. Given that this tends to be the overwhelmingly largest factor in the cost of creating software this is a bit of a problem.
If you can do a test, a loop, and a write, you're Turing complete IIRC. Hell, the DOS shell is Turing complete, your HP-12C is Turing complete.
So ANSI SQL with selects only may not be Turing complete, but pretty much all SQL implementations are, since they added loops, not to mention stored procedures etc.
All languages are Turing complete and equivalent from a computability standpoint. That's the sense in which it means nothing for a language to be Turing complete - they all are.
They are different in terms of expressive power, computational efficiency for different problems.
Can you do closures in HP-12C assembler? Of course! just write a Lisp interpreter in assembler, and there you go.
The posts like yours are the ones that actually create confusion around this term, because their authors are confused on what the Turing completeness is themselves, and so they spread their confusion on the others.
No, tests and loops are not what make computational stuff Turing complete -- nondeterministic finite automatons have both of them, and yet they're very weak computationally. I/O (assuming that's what you mean by write) is not even relevant. What matters the most is _memory_, and more importantly, _infinite, easily accessible_ memory. Nondeterministic finite automata have only finite amount of memory available, and thus they are very constrained on what they can compute. Nondeterministic pushdown automata, in spite of having infinite amount of memory available, don't have an easy access to it, and so, being stronger than finite automata, they're still weaker than Turing machines. But as soon as you add a second stack to a pushdown automaton, it suddenly becomes Turing complete. Hell, you can do it even with 6 integer variables instead of 2 stacks (I recall from my computation theory course that 3 integer variables are enough to encode a stack, so 6 will give you two stacks. Maybe you can go down even to 5 or 4). However, you absolutely require infinite memory, because, for sane definitions of "memory", every device with finite amount of memory (for instance, x86 PC) will not be able to compute anything more than deterministic finite automaton. From this point of view, all our computers are able to do is to match its input to a long and hairy regular expression. I hope that it will help some people realize how irrelevant is Turing completeness notion when it's used with regard to real life stuff.
You're way off the mark. While it annoys me that computers are constantly modeled as Turing Machines when it's much more appropriate that they be modeled as LBAs (Linear Bounded Automata) it does not have a huge bearing on computational feasibility in practice. While LBAs vs. TMs do have entirely different definitions and notions of what is and what is not undecidable (for instance, the halting problem is decidable for computers since they're LBAs. It's just impractical.) this only really becomes a theoretical difference.
Suggesting that an x86 PC is limited to the level of computational complexity of regular grammars is just wrong. LBAs are capable of context sensitive grammars and are much more capable than a FSM and absolutely can compute more.
In real life, computers can be modeled as turning machines without much issue. Memory is generally Big Enough(tm) that problems undecidable on TMs are terribly infeasible to attempt even though theoretically they are actually decidable.
And as long as the problem has a small enough state space, the computational expressiveness is the same. In practice, this occurs often enough that people still call computers turing machines even though they aren't.
Of course it makes more sense to model real life computers as LBAs. Still, it does not change the fact that given a computer, it has bounded, and not linearly bounded amount of memory, and that makes them no stronger than regular expressions. Of course that there's no practical difference for programmers. Of course the problem space is usually small enough. But it only proves my point: applying abstract terminology to real-life stuff does not necessarily make sense all the time.
It makes more sense to take. say, C or Python programming environment, instead of x86, as a computing model. It's enough to assume that malloc never fails to have genuinely Turing complete device.
Assuming that computer has finitely many states to be in because of finiteness of its memory, we can model it as a very large deterministic finite automaton. You cannot model a real computer as a LBA, because you don't necessarily have as many read-write memory as your input takes. If you think I'm wrong, please, tell me what makes you think that you can model real computers as LBAs.
This was helpful! I knew most of the pieces but not about the 3 integers encoding a stack. I presume integers here can be of any size (that is not constrained by number of bits) or else it won't be infinite amount of memory. Nevertheless, could you shed some more light? Is a push operation left shifting the integer and adding the pushed value...?
One integer variable is enough, because it effectively gives you infinite memory. Three times infinite memory is as much as one times infinite memory. What matters is not the number of integer variables, but which operations you're allowed to do on them. If 3 integer variables i,j,k with operations o1,o2,...,on are enough to encode a stack, then you can do the same with one integer variable x. You just represent i as all the bits in x whose position is 0 mod 3, j as all the bits whose position is 1 mod 3 and k as all the bits whose position is 2 mod 3. Then you just modify operations to only work on those bits that the operation applies to.
For example if you have an operation increment_i, and you start with i=j=k=0 then it works like this:
ijkijkijk...
start: i=0,j=0,k=0 and x = 000000000...
increment_i: now i=1,j=0,k=0 and x = 100000000...
increment_i: now i=2,j=0,k=0 and x = 000100000...
increment_i: now i=3,j=0,k=0 and x = 100100000...
increment_i: now i=4,j=0,k=0 and x = 000000100...
And if you increment_k then it works on the other bits:
ijkijkijk
increment_k: now i=4,j=0,k=1 and x = 001000100...
increment_k: now i=4,j=0,k=2 and x = 000001100...
increment_k: now i=4,j=0,k=3 and x = 001001100...
increment_k: now i=4,j=0,k=4 and x = 000000101...
Our model allowed us only to do INC, DEC and ZERO? on a counter, and it's easily seen that you cannot implement 2 counters using 1 counter with only ZERO?, INC and DEC, for instance by noting that you can recognize a^n b^n c^n language using automaton with two counters, you can (trivially) implement automaton with one counter using pushdown automaton, so if you were able to implement 2 counters using 1 counter, you could recognize a^n b^n c^n using pushdown automaton, which is easily seen to be impossible by applying pumping lemma for context free languages and usual characterization of pushdown automatons in terms of context free languages.
It seems that even 2 counters are enough for Turing machine. My class only came up with 3 counters for pushdown automaton, but I'm still happy with it, since we did it ourselves :)
Thanks. Helpful again. My understanding (after reading your first comment; would not have figured it out by myself!) was right (though incomplete still till I read the Wikipedia page).
fair enough - sufficiently large memory is also necessary. For that reason you couldn't write a Lisp interpreter on the 12C, although you could write one in the 12C language.
The point I was trying to make is that the simplest languages are Turing equivalent (given sufficient memory), because they have the necessary tests and control flow.
The TFA goes a bit astray IMHO when it says Turing completeness is not necessary for a language to be useful. Turing completeness is a low bar and even SQL as generally implemented hurdles it.
"If you can do a test, a loop, and a write, you're Turing complete IIRC."
No. What you got is a while-program. The main limitation of a while-program is the finite number of variables it has. Its computational power therefore depends on the data types it can work on.
Of course if you have stacks, dynamic arrays or equivalent then you're basically Turing-complete. Even if all you have is unbound integer arithmetic, you can emulate the infinite tape on the bits of a large integer.
If you only have finite types, then the while-program obviously has a finite number of states, so it's equivalent to an FSM.