if more people understood the rules of the logic then we wouldn't have so many people falling for the blatant sophistry espoused by political pundits & demagogues who dominate the media.
Not really. If more people understood the rules of logic, then also, more political pundits and demagogues would understand the rules of logic. Which only means that the sophistry would take the form of valid arguments with false premises. No amount of logic is going to help you if you believe false premises.
I'd say mathematical logic classes tend to be more detailed but less broad: they focus on the rigorous mathematical treatment of usually one or two relatively well-behaved logics, like propositional logic or first-order logic. Philosophical logic classes, by contrast, study these logics in less depth, but put more emphasis on comparisons between logics, the relationship between logic and natural-language argument and thought (and science), and so on.
Philosophy departments tend to offer two flavors of logic courses, for which my pet names are "baby logic" and "real logic."
"Baby logic" is a lot easier, and involves things like showing people how to do proofs in a relatively friendly proof system, some discussion of Aristotelian logic, relationship between logic and natural language, etc. Very much like what you describe. This course is normally a requirement for a degree in philosophy.
"Real logic," on the other hand, involves the rigorous definition of the language of first-order logic, its semantics, its proof theory, and the main metatheorems about the system. The tour the force is normally the completeness metatheorem for first-order logic, with a smaller emphasis on results like Löwenheim-Skolem and compactness. This is a very hard course, but not a requirement for all study tracks in a philosophy department; it also does serve as a weed-out for people who were looking at those tracks. This sounds like a "mathematical logic" as you describe it, but you seem to imply that this course would be taught in a math department, and not a philosophy department.
In fact, in my experience, mathematics and CS departments are less likely to teach this second kind of course as an end on its own. They tend to touch the material while discussing other stuff.
well you're explaining it away, not solving the problem.
But I don't think there's a serious problem here. Of course I'm explaining it away!
What do you believe makes this a problem? I can certainly agree that some proposed solutions to the mind-body problem have problems--like, for example, dualism has the problem of how the mental and the physical interact, which can be stated more concretely as "how can liquor affect your mind?"
the question remains, whether or not the information processing, computation, functionalist view can reproduce those experiences, or if there is something missing.
There is always something missing because science posits theoretical objects (like "information" and "computation"), and those theoretical objects are never the same thing as first-person experiences. At best, they're in some sort of predictively powerful structural correspondence to the experiences. That's what makes physicalist explanations of how liquor can make you drunk compelling and valuable, but it's also why they must fall short when you try to literally equate brain states with experience.
your view of incomplete descriptions simply reclassifies the gap as noumena, existing (in a physical substrate) but ineffable.
What exactly do you mean by "physical" and by "ineffable" in this case? If by "physical substrate" you mean "the theoretical objects involved in the science of physics," then no, I'm not proposing a "physical" substrate. And when it comes to "ineffable," well, I'm going to have to excuse myself because don't have time right now to argue about the beetles in the box:-(. But the short version: of course it's ineffable; language is public.
They were taught, very firmly, to treat each layer of abstraction as entirely unique and unrelated to the other layers.
...which is correct at the logical level, but not the physical level, indeed. Same suspicion as before: they've picked the wrong abstractions. I'd restate your point the following way: physical performance considerations constrain which are the correct abstractions to pick.
Basically, two of the goals of computer engineering are:
Build highly modular systems out of reusable, easily modifiable pieces.
Have those systems perform fast enough.
The problem is that most programmers have a very hard time nailing both of those at the same time. Using abstractions performantly requires one to have an intuitive, high-level understanding of how the abstractions will translate to the physical layer.
For example, under heavy load, reading a data file backwards is a nasty performance hit on disk I/O because you still have to often spin the disk to get back around to the previous block.
...therefore the correct abstraction for file access, if you must process the whole file, should be that reading a file produces a stream of items, you write the algorithm so that it consumes the input in whatever order the stream supplies it, and so that it processes the smallest sequential "window" of the input that it possibly can work with. Therefore, the abstractions you choose should not be incompatible with these considerations. Recursive list algorithms, in particular, fail it here.
In my experience, the corresponding kind of idiocy in the C/Java world is hardcoded SQL queries with awful performance. In fact, SQL is a perfect example here, because writing performant SQL requires you to understand at a high level how your queries are be translated into sequential execution plans. If you don't have such a high-level mental model, you can very easily write logically correct queries that perform a thousand-fold worse than the best logically equivalent ones. To use the abstraction performantly, you also need a model of how it's going to perform. The good news is that the latter model can normally be abstract; you can think of SQL query execution in terms of query rewriting, pushing filtering conditions down to table access methods, statistical properties of tables like index value skews, etc.
PS: my job involves writing Lisp programs that generate SQL queries for high-performance bulk data transformations, so everything I'm saying here is completely unsurprising when you look at it from that angle. The code has to take analyze schema descriptions to generate abstract syntax trees that get translated into largely SQL text that must execute as efficiently as possible. There is absolutely no way you can do this without considerable abstraction and reasoning about the performance implications of every bit--including the performance characteristics of third-party RDBMSes that you have little control over...
"1.1 The world is the totality of facts, not of things." --Ludwig Wittgenstein, Tractatus Logico-Philosophicus
That's the best short description of relational modeling I've ever found, for somebody used to object-oriented modeling. Basically, it's a change of ontology: the OO modeler tends to think of the world as being made up of things, each of which has some repertoire of properties; the world is a big set of things, related by a few universal laws. The relational modeler, on the other hand, conceives of things as unanalyzable wholes, and everything interesting about things is how they are related to other things by facts, and how those facts are related to other facts by logic.
I don't necessarily agree with the arguments of Searle who seems to think the brain is a special substance. On the evidence it's at best equivocal with the possibility that (i) the brain is simply much more complex than was assumed in previous generations (ii) brains are embodied, bodies are only causally effective in an environment that is also causally effective. A computer program is only a simulation of an arbitrarily separated process.
Yeah, you're saying the same kind of stuff I was saying in another post... Needless to say, I agree!
Now, Searle isn't only arguing that the brain is a special substance for "mental states" he's also suggesting it is a special substance for "qualia" or as Antonio Damasio calls it "the feeling of what happens".
And I think the best objection to that is that the perceived need for a separate "substance" to cover the "mental" comes from the assumption that natural sciences like physics and biology are complete descriptions of a substance, call it "the physical." But basically, if you regard the results of the natural sciences as incomplete descriptions of something that bears predictively powerful structural correspondences to a socially-shared Lebenswelt, the difficulty disappears. Natural science's descriptions of first-person experience always fall short of first-person experience simply because they're descriptions, and not actual first-person experiences.
The strong AI problem is then trivial because it really only comes down to whether we can believe folk-psychological accounts that attribute first-person experiences to machines in the same way we do when they're predicated of other people. And I don't think there's any serious reason why we couldn't--remember that our shared belief that other people have first-person experiences is the result of social training, not a foundationalist rational justification (i.e., the other minds problem).
You understand something if and to the extent that you can correctly predict it in advance.
I'm not a great fan of Searle (I think "intentionality" is magical pixie dust), but this is precisely the behaviorist/operationalist bias that GP is alluding to. Basically, good old-fashioned AI is flawed because it frames its project in terms of conceiving of the mind as a state machine, and AI as design and implementation of similar state machines.
The basic flaw is the same as in behavioralism: the failure to understand how the "mental" complexity of the organism is intimately tied to its physical embodiment and how it enacts an ecological niche. This is basically the philosophical space occupied by approaches such as embodied cognition, and situated cognition.
The foundation of modern mathematical thought was a philosophical work called the Principia Mathematica.
Um, no, not really. Rather, foundationalist philosophers of mathematics, and a few philosophically oriented mathematicians used to claim that mathematics was founded on logic and/or set theory. There were always philosophers who disagreed with the whole foundationalist project for mathematics, and over time those folks have gotten more and more influential.
Computer science has given a hell of a boost to a lot of work that started out in the foundations of mathematics bin, but the work in question tends to be constructive mathematics à la Brouwer and similar folk, and not the logicist mathematics espoused by Russell (big exception: type theory, but type theory is often constructivized). This is because constructive mathematics tends to be computable, and constructive proofs can be mechanically translated into computer programs that solve mathematical problems.
So roles are basically interfaces, but with type-checking whether an object satifies the interfaces deferred until runtime. That's a good idea; I've personally actually wanted very long to have something like this in Java. But it's basically a small improvement on interface specifications, which comes down to type systems.
Why do you Perl folk like to talk about every simple thing as if it was the product of your profound knowledge of something else that's only tenuously related to computer science? For example, Larry Wall is pretty insignificant as a linguist, yet him and a bunch of other Perlfolk keep attributing all sorts of hare-brained ideas to the supposed fact that he's a linguist, and therefore supposedly has some great insight into how natural languages work and how people think. Um, no.
It gives you the warm and fuzzy feeling that you feel when you think you understand something. Hopefully, you later grow up, seriously read a lot more stuff (and by "seriously" I mean "charitably"), and realize that it's not a very good book after all.
I think what you really want is a good Scheme implementation. MzScheme might do it for you, unless you want something more compilation-oriented (though MzScheme does have JIT these days, I hear).
The result was the _excessive_ use of abstraction, to such extents that I had to go in and violate the abstractions to explain 'You are presenting the data in the wrong order: if you present it in the correct order, which you have been taught not to think about, you eliminate 95% of the load that you are seeing.
My first reaction to this is that it doesn't sound as "excessive" use of abstraction; rather, it sounded either as use of incorrect abstractions, or as a failure to model the execution of the algorithm. Two points here:
Unordered data structures aren't any more "abstract" than ordered ones; they just have an interface that obeys a different contract.
If an unordered data structure truly is an architectural requirement in the system at some level, but ordered execution of steps is needed to guarantee acceptable performance, then the program arguably should analyze the unordered data structure at some level to compute the best order of execution, and then execute in that order. (This is what I mean above as "modeling the execution of the algorithm": write the program so it can reason about what's the best order to do stuff, performance-wise. Even simple heuristics can make a difference.)
C and Java programmers are, as a general group, very bad at using abstractions too. Most often, they just use too few of them, the resulting code is too tightly bound together, and it's difficult to reuse or replace individual pieces of the resulting programs. Too many constructs that specify how to do something, instead of what result to achieve. (Compare for loops to map.)
Structuring a system in terms of nested abstractions is not at all bad for later performance tuning. In fact, what you described above sounds like the correct way to optimize such a system: find places where the interface between nested abstractions is a bottleneck, and rewrite in a more concrete manner to eliminate the cost. Basically, if you have poorly performing module A written in terms of B and C, replace A with a module A' that incorporates the necessary features of B and C, but without the abstraction layer bottleneck.
However, I object to calling that "violating the abstractions," because the interface of A' to its clients remains the same as before, and B and C may still be used in other places where they do help. All you're changing is the internal details of a module, so as not to use costly lower-level abstractions. Abstraction is about hiding internal details of the part of the system. If somebody insists that A should use B and C in the name of "abstraction," they're getting the idea completely backwards: the point of abstraction is precisely to make it possible to change A without having to change anything else. But the trick is only do this in places where performance is actually bad, so you reap the benefits of code reuse or implementation speed elsewhere in the system, where you do use B and C.
A compiled language, like C or even Java, can also try to deal with this by unrolling loops and transforming structures to avoid such classic problems. An interpreted language cannot, and the programmer must understand the limitations, which these gentlemen were never taught.
Um, there are plenty of Lisp systems out there that use compilation. What makes you think that Lisp systems cannot unroll loops?
There is, and you just quoted it. The best part of LISP is that there's no bloody syntax; everything is clean, regular and simple.
No, this isn't quite true. Lisp has plenty of syntax; they just call it "special forms." In fact, Lisp has arbitrarily much syntax, given mechanisms to define your own special forms (i.e., macros). Note that this isn't all good, because people can go crazy with macros and write code that's really hard to understand and, what's worse, really hard to debug.
What Lisp doesn't have a lot of is lexical syntax, nor operator precendence. If you look at a Lisp program, there may be unfamiliar syntax in there (i.e., macros whose syntax you don't know), but faced with that, you can at least tell how stuff is nested. (The one big exception to the lexical syntax part is reader macros. Reader macros are utterly evil, if you ask me, precisely because their use makes the above not hold anymore.)
After programming for several years in Lisp, I must say the syntax has me spoiled. Every time I try to understand a complex arithmetical or boolean expression in Java or SQL, I actually end up translating it to properly indented Lisp code in a scratch file, which makes it much, much easier to read. "Oh, so this is an addition of three summands, the first of which is the quotient of the subtraction of two things and the addition of four others."
Also, every time I try to get my head around something like Haskell, I just can never remember all the line-noise little infix operators that Haskell programmers insist on using. (In Lisp code you might have all sorts of crazy operators, too, but they'd just be functions or macros with long, descriptive names, like MONAD-BIND instead of >>= or whatever the hell line noise operator they use in Haskell for that.)
The problem results from following the most elementary paradigms of Lisp programming: ignore what is happening at the higher and lower levels, and avoid specifying the interfaces to those other details in detail. The results are very painful to clean up.
I think your idea of this "elementary paradigm of Lisp programming" is way too monolithic. I do agree that there's a loudmouth Lisp programming school that preaches some really awful practices, like "use (singly-linked) lists as your only data structure."
However, the worst Lisp code I see suffers from too little abstraction, not too much. The worst, stupidest case is using lists as records, and accessing the "fields" of a "record" through concrete list operations. ("Ok, I want to get the date of this transaction. Um, is that the third element of the list, or the fourth one?" Or even worse: "Aaaargh, this code I'm reading actually uses the cdadr procedure!") Then they use their "records" in an inner loop, and their O(n) algorithm ends up with an O(n^2) implementation. And when you try to fix it, well, you have to find all the places they create a new "record" to create a real record data structure, and find all the places they access the "fields" and do the same.
It's particularly annoying because the problem should never have happened: the program should have been written from the beginning to treat the records as an abstract data type, instantiated and accessed only through specialized procedures dealing with that type. Then you can change the implementation of the type without changing the code that uses the type. (And if the program could really benefit from using lists as a syntactic representation of the type, then the right way to do it is to provide functions that translate the between the private implementation of the type and the list-based external representation.)
But of course, if you write your code like that from the beginning, you might as well not use lists as the freaking implementation type to start with. The lesson is precisely what I started with: the loudmouth "use (singly-linked) lists as your only data structure" school of Lisp programming is evil.
Why not instead of lists, use maps + lists ? You can of course express a map with lists but maps/"names" are so natural to think with that I think it would be easier to express ideas with it. "Naming" is very natural, and I don't think names as lists of lists.
Take care to distinguish between the syntax of the language and the interpretation of the expressions in the language. Lisp uses the native syntax for lists to represent code. That doesn't mean that all the code must be translated into lists data structures. For example, you can have a macro that transforms a list representation of a map to code to construct an actual map at runtime.
That's because C deals with how computers actually think.
Only to the extent that processors are designed to run C programs; and ss it happens, contemporary processor designs are more complex than the would otherwise need to be, in order to better support C programs. Look at Itanium as a (commercially) failed attempt to design processors otherwise.
IQ is a value judgement posing as a fact judgement. If somebody has a high IQ, it must means that they performed well at a task that the designers of the IQ test chose as a "good" task, at the expense of other tasks. Basically, IQ indirectly measures skills that are valuable in certain social contexts. The division of labor in our economy makes us distinguish different skill sets as being suited for different kinds of labor, and the economic arrangements remunerates some kinds of labor at a higher rate than others.
A different society could value different skill sets at different rates than we do. Therefore, those societies' tests for their own "valuable skill quotients" would correspondingly have different results than ours.
All of this only reinforces the point I was making: IQ and intelligence aren't intrinsic properties of people, but rather, a contextual set of relationships between people. Talk about intelligence and IQ as reified properties is basically hiding historically contingent social relations under a seemingly timeless cosmological blanket.
No, it's not. It's providing a counterexample to a particular claim, that happens to be in the part of math that you term "arithmetic". In particular, there's no reason to expect that this incompleteness property is restricted to axiom systems derived from arithmetic.
That's a silly objection. What you're saying just means that we could, in principle, show that some other axiomatic theory is incomplete. That's certainly true, but Gödel's incompleteness theorem for arithmetic is still a theorem that proves that arithmetic is incomplete, and says nothing about any other axiomatic theory or part of math. If you got some proof that some other, non-arithmetical axiomatic system is incomplete, that'd be an interesting result, but it's not Gödel's theorem.
Penrose, Hofstadter and you all share a basic assumption: that there exists a "real" property that the word "intelligence" denotes. I think that assumption is flawed.
The alternative view is that "intelligence" is just a term in a cultural classificatory scheme. This implies several things:
There isn't really a set of necessary and sufficient conditions for something to be "intelligent." What the various uses of the word share is a set of family resemblances.
The classification is tied to a bunch of cultural practices. In the case of "intelligence," it's easy to come up with alternatives: the distribution and specialization of labor, and the assignment of rights and responsibilities. In the first case, we give certain jobs to people who are "intelligent," while giving others to people who are "not intelligent"; in the second, we assign the full range of civil rights and responsibilities to people who have a fully developed "intelligence," but deny rights to, and excuse from responsibilities, people whose "intelligence" is lacking (children, defense of insanity).
The term, therefore, is culturally variable and historically contingent. A hundred years ago, it was common opinion among educated westerners that women, children and non-whites were not "intelligent" and did not "think," often with specialized technical vocabulary for explaining the cognitive faculties of "non-intelligent" humans. Today people have seemingly serious arguments about whether a computer can be "intelligent." What happened during that time? Universal suffrage, decolonization, the rise and fall of behaviorist psychology, the rise of cognitive science, increasing secularization of culture, etc. (The derogation of women's and minorities' cognition does continue, however, but expressed in newer terms: instead of saying that women and negroes experience "henids" instead of "thinking in ideas," people today say that women or African-Americans on average have lower IQ than white men, and that IQ is subject to significant inheritance (see Lawrence Summers or The Bell Curve)).
Basically, arguments about whether machines can "think" are cosmological arguments; what's really at stake is not what machines can do, but rather, our ideas of what the world is, what people are, and how people relate to the rest of the world; in particular, the relationship between people and machines.
So now we come at my personal, half-serious test for machine intelligence: can I bring a civil lawsuit against a computer, or the state press criminal charges against it? More generally: can a machine have responsibilities in the same sense that a person does?
The first point of this is that
the most fundamental gulf between people and machines isn't a physical or a cognitive gulf: it's a social gulf. Whether a machine has responsibilities isn't determined by any property intrinsic to the machine itself; it's determined by how people actually relate to the machine. Intrinsic properties of the machine aren't irrelevant, but they're neither necessary nor sufficient.
The other point is to highlight that the word "intelligence" in AI is being used in a technical and artificially narrow, purely cognitive sense, that doesn't reflect the whole range of implications that the word has in our culture. If we take the broader view, "intelligence" isn't just about cognition; it's at least as much about moral agency. We can turn the whole machine intelligence issue on its head by suggesting that we don't call humans "intelligent" because we catalogued their intrinsic cognitive faculties and found that they met an independent criterion of "intelligence"; rather, we call them "intelligent" because we regard them as moral agents, and from that assumption, it follows that they are are intelligent. Then, the reason we don't regard machines as intelligent is simply that we don't regard them as moral agents.
One might argue that the brain is merely a biological computer not fully understood.
How would that be an argument, and not just an analogy?
One might argue that my bedroom walls are a physical computer not fully understood, simply by stating some structural correspondences between it and some Turing machine. Where does that leave arguments to the effect that "the brain is a computer"?
If you picked a set of axioms that could prove a false statement of arithmetic, I wouldn't call those a "set of axioms for arithmetic" in the first place. I know I'm playing a bit fast and loose with all of this, but it does seem clear to me that if a set of axioms proves a statement that isn't true in all models of arithmetic, then one shouldn't be calling it "a set of axioms for arithmetic."
If it's possible to enumerate all valid proofs I propose the following proving algorithm: Run through all valid proofs; once you get to a proof whose conclusion is the theorem you want to prove, return that proof. [if you don't know whether your theorem is true or not, run the above algorithm on its negation as well].
That needs a couple of small amendments:
You shouldn't run the algorithm on the statement and its negation in sequence, because the basic algorithm will never terminate for an unprovable statement. To harden the algorithm, you should interleave the runs for the statement and its negation: as you enumerate each valid proof, you check whether the conclusion is either your statement or its negation.
Strictly speaking, what's relevant here is not the "truth" of a statement, but rather its validity given the axiomatic theory. A valid statement is one that is true under all interpretations of the theory; an invalid statement is false under all interpretations of the theory; a contingent statement is one that's neither valid nor invalid, since it's true under some interpretations of the theory and false under others.
Intuitively, your algorithm fails if the theory admits of contingent statements (as first-order logic does), or if the theory is incomplete (as arithmetic is). If you feed it a contingent statement, it will never terminate, since no proof will have either the statement or its negation as its conclusion. Same goes if your theory is incomplete and you feed it one of its Gödel sentences.
If you can prove that for every statement in the language, your axiomatic theory has a proof either of that statement or its negation, then your algorithm works for that theory. (The textbook I used calls such theories syntactically complete, but books often use just "complete" for this property, which is different from Gödel's "(in)completeness"...)
(All of the above assumes the axiomatic theory is sound to start with, i.e., there are no proofs of invalid statements. If your theory is unsound, you've got bigger problems.)
Benchmarks have shown that Via processors have much lower floating-point performance compared to their competitors (i.e. Intel and AMD) so why exactly are they using Via chips to achieve mathematical proofs?
A formal proof is not a numerical calculation. A formal proof is, basically, a set of premises, a conclusion, and a set of steps that justifies the conclusion, given those premises and a set of rules that define your proof system. The premises and conclusions are logical formulas, which are basically symbolic trees, and the proof steps relating the premises to the conclusion are all discrete too. So there is no essential numerical calculation going on at any point here.
Godel's completeness theorem states that every statement that follows from the axioms is in fact deducible from the axioms in finitely many logical steps.
That Gödel's Completeness Theorem for first-order logic--predicates, individuals, quantifiers ("for all," "exists"), and truth connectives (not, or, and).
Godel also has proved an "incompleteness" theorem. That more famous (and less important) result is that there are statements that are true in specific models yet not provable from the axioms.
The incompleteness theorem is about arithmetic: natural numbers defined in terms of 0 and the successor relation, addition and multiplication. For any set of axioms you pick for arithmetic, there are true statements of arithmetic that cannot be proven from those axioms.
It implies that there is no algorithm to decide whether a given statement is true -- but this has nothing to do with enumerating all true statements.
I'm not completely sure of how relevant the incompleteness of arithmetic is for what you're saying, but I am sure of this: first-order logic is complete, but the validity of a statement in first-order logic is undecidable. Therefore, you don't need to bring in Gödel's incompleteness theorem for arithmetic to conclude that in many important cases.
Not really. If more people understood the rules of logic, then also, more political pundits and demagogues would understand the rules of logic. Which only means that the sophistry would take the form of valid arguments with false premises. No amount of logic is going to help you if you believe false premises.
Philosophy departments tend to offer two flavors of logic courses, for which my pet names are "baby logic" and "real logic."
"Baby logic" is a lot easier, and involves things like showing people how to do proofs in a relatively friendly proof system, some discussion of Aristotelian logic, relationship between logic and natural language, etc. Very much like what you describe. This course is normally a requirement for a degree in philosophy.
"Real logic," on the other hand, involves the rigorous definition of the language of first-order logic, its semantics, its proof theory, and the main metatheorems about the system. The tour the force is normally the completeness metatheorem for first-order logic, with a smaller emphasis on results like Löwenheim-Skolem and compactness. This is a very hard course, but not a requirement for all study tracks in a philosophy department; it also does serve as a weed-out for people who were looking at those tracks. This sounds like a "mathematical logic" as you describe it, but you seem to imply that this course would be taught in a math department, and not a philosophy department.
In fact, in my experience, mathematics and CS departments are less likely to teach this second kind of course as an end on its own. They tend to touch the material while discussing other stuff.
But I don't think there's a serious problem here. Of course I'm explaining it away!
What do you believe makes this a problem? I can certainly agree that some proposed solutions to the mind-body problem have problems--like, for example, dualism has the problem of how the mental and the physical interact, which can be stated more concretely as "how can liquor affect your mind?"
There is always something missing because science posits theoretical objects (like "information" and "computation"), and those theoretical objects are never the same thing as first-person experiences. At best, they're in some sort of predictively powerful structural correspondence to the experiences. That's what makes physicalist explanations of how liquor can make you drunk compelling and valuable, but it's also why they must fall short when you try to literally equate brain states with experience.
What exactly do you mean by "physical" and by "ineffable" in this case? If by "physical substrate" you mean "the theoretical objects involved in the science of physics," then no, I'm not proposing a "physical" substrate. And when it comes to "ineffable," well, I'm going to have to excuse myself because don't have time right now to argue about the beetles in the box :-(. But the short version: of course it's ineffable; language is public.
...which is correct at the logical level, but not the physical level, indeed. Same suspicion as before: they've picked the wrong abstractions. I'd restate your point the following way: physical performance considerations constrain which are the correct abstractions to pick.
Basically, two of the goals of computer engineering are:
The problem is that most programmers have a very hard time nailing both of those at the same time. Using abstractions performantly requires one to have an intuitive, high-level understanding of how the abstractions will translate to the physical layer.
...therefore the correct abstraction for file access, if you must process the whole file, should be that reading a file produces a stream of items, you write the algorithm so that it consumes the input in whatever order the stream supplies it, and so that it processes the smallest sequential "window" of the input that it possibly can work with. Therefore, the abstractions you choose should not be incompatible with these considerations. Recursive list algorithms, in particular, fail it here.
In my experience, the corresponding kind of idiocy in the C/Java world is hardcoded SQL queries with awful performance. In fact, SQL is a perfect example here, because writing performant SQL requires you to understand at a high level how your queries are be translated into sequential execution plans. If you don't have such a high-level mental model, you can very easily write logically correct queries that perform a thousand-fold worse than the best logically equivalent ones. To use the abstraction performantly, you also need a model of how it's going to perform. The good news is that the latter model can normally be abstract; you can think of SQL query execution in terms of query rewriting, pushing filtering conditions down to table access methods, statistical properties of tables like index value skews, etc.
PS: my job involves writing Lisp programs that generate SQL queries for high-performance bulk data transformations, so everything I'm saying here is completely unsurprising when you look at it from that angle. The code has to take analyze schema descriptions to generate abstract syntax trees that get translated into largely SQL text that must execute as efficiently as possible. There is absolutely no way you can do this without considerable abstraction and reasoning about the performance implications of every bit--including the performance characteristics of third-party RDBMSes that you have little control over...
"1.1 The world is the totality of facts, not of things." --Ludwig Wittgenstein, Tractatus Logico-Philosophicus
That's the best short description of relational modeling I've ever found, for somebody used to object-oriented modeling. Basically, it's a change of ontology: the OO modeler tends to think of the world as being made up of things, each of which has some repertoire of properties; the world is a big set of things, related by a few universal laws. The relational modeler, on the other hand, conceives of things as unanalyzable wholes, and everything interesting about things is how they are related to other things by facts, and how those facts are related to other facts by logic.
Here's a very condensed outline of the Tractatus ; the parts you want to see are primarily (1) and (2).
Yeah, you're saying the same kind of stuff I was saying in another post... Needless to say, I agree!
And I think the best objection to that is that the perceived need for a separate "substance" to cover the "mental" comes from the assumption that natural sciences like physics and biology are complete descriptions of a substance, call it "the physical." But basically, if you regard the results of the natural sciences as incomplete descriptions of something that bears predictively powerful structural correspondences to a socially-shared Lebenswelt, the difficulty disappears. Natural science's descriptions of first-person experience always fall short of first-person experience simply because they're descriptions, and not actual first-person experiences.
The strong AI problem is then trivial because it really only comes down to whether we can believe folk-psychological accounts that attribute first-person experiences to machines in the same way we do when they're predicated of other people. And I don't think there's any serious reason why we couldn't--remember that our shared belief that other people have first-person experiences is the result of social training, not a foundationalist rational justification (i.e., the other minds problem).
I'm not a great fan of Searle (I think "intentionality" is magical pixie dust), but this is precisely the behaviorist/operationalist bias that GP is alluding to. Basically, good old-fashioned AI is flawed because it frames its project in terms of conceiving of the mind as a state machine, and AI as design and implementation of similar state machines.
The basic flaw is the same as in behavioralism: the failure to understand how the "mental" complexity of the organism is intimately tied to its physical embodiment and how it enacts an ecological niche. This is basically the philosophical space occupied by approaches such as embodied cognition, and situated cognition.
Um, no, not really. Rather, foundationalist philosophers of mathematics, and a few philosophically oriented mathematicians used to claim that mathematics was founded on logic and/or set theory. There were always philosophers who disagreed with the whole foundationalist project for mathematics, and over time those folks have gotten more and more influential.
Computer science has given a hell of a boost to a lot of work that started out in the foundations of mathematics bin, but the work in question tends to be constructive mathematics à la Brouwer and similar folk, and not the logicist mathematics espoused by Russell (big exception: type theory, but type theory is often constructivized). This is because constructive mathematics tends to be computable, and constructive proofs can be mechanically translated into computer programs that solve mathematical problems.
So roles are basically interfaces, but with type-checking whether an object satifies the interfaces deferred until runtime. That's a good idea; I've personally actually wanted very long to have something like this in Java. But it's basically a small improvement on interface specifications, which comes down to type systems.
Why do you Perl folk like to talk about every simple thing as if it was the product of your profound knowledge of something else that's only tenuously related to computer science? For example, Larry Wall is pretty insignificant as a linguist, yet him and a bunch of other Perlfolk keep attributing all sorts of hare-brained ideas to the supposed fact that he's a linguist, and therefore supposedly has some great insight into how natural languages work and how people think. Um, no.
It gives you the warm and fuzzy feeling that you feel when you think you understand something. Hopefully, you later grow up, seriously read a lot more stuff (and by "seriously" I mean "charitably"), and realize that it's not a very good book after all.
I think what you really want is a good Scheme implementation. MzScheme might do it for you, unless you want something more compilation-oriented (though MzScheme does have JIT these days, I hear).
My first reaction to this is that it doesn't sound as "excessive" use of abstraction; rather, it sounded either as use of incorrect abstractions, or as a failure to model the execution of the algorithm. Two points here:
C and Java programmers are, as a general group, very bad at using abstractions too. Most often, they just use too few of them, the resulting code is too tightly bound together, and it's difficult to reuse or replace individual pieces of the resulting programs. Too many constructs that specify how to do something, instead of what result to achieve. (Compare for loops to map.)
Structuring a system in terms of nested abstractions is not at all bad for later performance tuning. In fact, what you described above sounds like the correct way to optimize such a system: find places where the interface between nested abstractions is a bottleneck, and rewrite in a more concrete manner to eliminate the cost. Basically, if you have poorly performing module A written in terms of B and C, replace A with a module A' that incorporates the necessary features of B and C, but without the abstraction layer bottleneck.
However, I object to calling that "violating the abstractions," because the interface of A' to its clients remains the same as before, and B and C may still be used in other places where they do help. All you're changing is the internal details of a module, so as not to use costly lower-level abstractions. Abstraction is about hiding internal details of the part of the system. If somebody insists that A should use B and C in the name of "abstraction," they're getting the idea completely backwards: the point of abstraction is precisely to make it possible to change A without having to change anything else. But the trick is only do this in places where performance is actually bad, so you reap the benefits of code reuse or implementation speed elsewhere in the system, where you do use B and C.
Um, there are plenty of Lisp systems out there that use compilation. What makes you think that Lisp systems cannot unroll loops?
No, this isn't quite true. Lisp has plenty of syntax; they just call it "special forms." In fact, Lisp has arbitrarily much syntax, given mechanisms to define your own special forms (i.e., macros). Note that this isn't all good, because people can go crazy with macros and write code that's really hard to understand and, what's worse, really hard to debug.
What Lisp doesn't have a lot of is lexical syntax, nor operator precendence. If you look at a Lisp program, there may be unfamiliar syntax in there (i.e., macros whose syntax you don't know), but faced with that, you can at least tell how stuff is nested. (The one big exception to the lexical syntax part is reader macros. Reader macros are utterly evil, if you ask me, precisely because their use makes the above not hold anymore.)
After programming for several years in Lisp, I must say the syntax has me spoiled. Every time I try to understand a complex arithmetical or boolean expression in Java or SQL, I actually end up translating it to properly indented Lisp code in a scratch file, which makes it much, much easier to read. "Oh, so this is an addition of three summands, the first of which is the quotient of the subtraction of two things and the addition of four others."
Also, every time I try to get my head around something like Haskell, I just can never remember all the line-noise little infix operators that Haskell programmers insist on using. (In Lisp code you might have all sorts of crazy operators, too, but they'd just be functions or macros with long, descriptive names, like MONAD-BIND instead of >>= or whatever the hell line noise operator they use in Haskell for that.)
I think your idea of this "elementary paradigm of Lisp programming" is way too monolithic. I do agree that there's a loudmouth Lisp programming school that preaches some really awful practices, like "use (singly-linked) lists as your only data structure."
However, the worst Lisp code I see suffers from too little abstraction, not too much. The worst, stupidest case is using lists as records, and accessing the "fields" of a "record" through concrete list operations. ("Ok, I want to get the date of this transaction. Um, is that the third element of the list, or the fourth one?" Or even worse: "Aaaargh, this code I'm reading actually uses the cdadr procedure!") Then they use their "records" in an inner loop, and their O(n) algorithm ends up with an O(n^2) implementation. And when you try to fix it, well, you have to find all the places they create a new "record" to create a real record data structure, and find all the places they access the "fields" and do the same.
It's particularly annoying because the problem should never have happened: the program should have been written from the beginning to treat the records as an abstract data type, instantiated and accessed only through specialized procedures dealing with that type. Then you can change the implementation of the type without changing the code that uses the type. (And if the program could really benefit from using lists as a syntactic representation of the type, then the right way to do it is to provide functions that translate the between the private implementation of the type and the list-based external representation.)
But of course, if you write your code like that from the beginning, you might as well not use lists as the freaking implementation type to start with. The lesson is precisely what I started with: the loudmouth "use (singly-linked) lists as your only data structure" school of Lisp programming is evil.
Take care to distinguish between the syntax of the language and the interpretation of the expressions in the language. Lisp uses the native syntax for lists to represent code. That doesn't mean that all the code must be translated into lists data structures. For example, you can have a macro that transforms a list representation of a map to code to construct an actual map at runtime.
Only to the extent that processors are designed to run C programs; and ss it happens, contemporary processor designs are more complex than the would otherwise need to be, in order to better support C programs. Look at Itanium as a (commercially) failed attempt to design processors otherwise.
IQ is a value judgement posing as a fact judgement. If somebody has a high IQ, it must means that they performed well at a task that the designers of the IQ test chose as a "good" task, at the expense of other tasks. Basically, IQ indirectly measures skills that are valuable in certain social contexts. The division of labor in our economy makes us distinguish different skill sets as being suited for different kinds of labor, and the economic arrangements remunerates some kinds of labor at a higher rate than others.
A different society could value different skill sets at different rates than we do. Therefore, those societies' tests for their own "valuable skill quotients" would correspondingly have different results than ours.
All of this only reinforces the point I was making: IQ and intelligence aren't intrinsic properties of people, but rather, a contextual set of relationships between people. Talk about intelligence and IQ as reified properties is basically hiding historically contingent social relations under a seemingly timeless cosmological blanket.
That's a silly objection. What you're saying just means that we could, in principle, show that some other axiomatic theory is incomplete. That's certainly true, but Gödel's incompleteness theorem for arithmetic is still a theorem that proves that arithmetic is incomplete, and says nothing about any other axiomatic theory or part of math. If you got some proof that some other, non-arithmetical axiomatic system is incomplete, that'd be an interesting result, but it's not Gödel's theorem.
Penrose, Hofstadter and you all share a basic assumption: that there exists a "real" property that the word "intelligence" denotes. I think that assumption is flawed.
The alternative view is that "intelligence" is just a term in a cultural classificatory scheme. This implies several things:
Basically, arguments about whether machines can "think" are cosmological arguments; what's really at stake is not what machines can do, but rather, our ideas of what the world is, what people are, and how people relate to the rest of the world; in particular, the relationship between people and machines.
So now we come at my personal, half-serious test for machine intelligence: can I bring a civil lawsuit against a computer, or the state press criminal charges against it? More generally: can a machine have responsibilities in the same sense that a person does?
The first point of this is that the most fundamental gulf between people and machines isn't a physical or a cognitive gulf: it's a social gulf. Whether a machine has responsibilities isn't determined by any property intrinsic to the machine itself; it's determined by how people actually relate to the machine. Intrinsic properties of the machine aren't irrelevant, but they're neither necessary nor sufficient.
The other point is to highlight that the word "intelligence" in AI is being used in a technical and artificially narrow, purely cognitive sense, that doesn't reflect the whole range of implications that the word has in our culture. If we take the broader view, "intelligence" isn't just about cognition; it's at least as much about moral agency. We can turn the whole machine intelligence issue on its head by suggesting that we don't call humans "intelligent" because we catalogued their intrinsic cognitive faculties and found that they met an independent criterion of "intelligence"; rather, we call them "intelligent" because we regard them as moral agents, and from that assumption, it follows that they are are intelligent. Then, the reason we don't regard machines as intelligent is simply that we don't regard them as moral agents.
If you picked a set of axioms that could prove a false statement of arithmetic, I wouldn't call those a "set of axioms for arithmetic" in the first place. I know I'm playing a bit fast and loose with all of this, but it does seem clear to me that if a set of axioms proves a statement that isn't true in all models of arithmetic, then one shouldn't be calling it "a set of axioms for arithmetic."
That needs a couple of small amendments:
Intuitively, your algorithm fails if the theory admits of contingent statements (as first-order logic does), or if the theory is incomplete (as arithmetic is). If you feed it a contingent statement, it will never terminate, since no proof will have either the statement or its negation as its conclusion. Same goes if your theory is incomplete and you feed it one of its Gödel sentences.
If you can prove that for every statement in the language, your axiomatic theory has a proof either of that statement or its negation, then your algorithm works for that theory. (The textbook I used calls such theories syntactically complete, but books often use just "complete" for this property, which is different from Gödel's "(in)completeness"...)
(All of the above assumes the axiomatic theory is sound to start with, i.e., there are no proofs of invalid statements. If your theory is unsound, you've got bigger problems.)
A formal proof is not a numerical calculation. A formal proof is, basically, a set of premises, a conclusion, and a set of steps that justifies the conclusion, given those premises and a set of rules that define your proof system. The premises and conclusions are logical formulas, which are basically symbolic trees, and the proof steps relating the premises to the conclusion are all discrete too. So there is no essential numerical calculation going on at any point here.
That Gödel's Completeness Theorem for first-order logic--predicates, individuals, quantifiers ("for all," "exists"), and truth connectives (not, or, and).
The incompleteness theorem is about arithmetic: natural numbers defined in terms of 0 and the successor relation, addition and multiplication. For any set of axioms you pick for arithmetic, there are true statements of arithmetic that cannot be proven from those axioms.
I'm not completely sure of how relevant the incompleteness of arithmetic is for what you're saying, but I am sure of this: first-order logic is complete, but the validity of a statement in first-order logic is undecidable. Therefore, you don't need to bring in Gödel's incompleteness theorem for arithmetic to conclude that in many important cases.
Depending on what you mean by "whites," you may be reading those numbers wrong. The US Census Bureau classifies along two independent criteria:
The page you linked estimates that 73.9% of the US population is "white." However, Non-Hispanic White is 66%, actually.