I have tried blinding cameras with lasers. It's hard.
It's not hard, however, to shoot something the size of a camera from 100 yards away using a hunting rifle. I suspect that the weakness of this vehicle, assuming that the rusty armor can withstand assault rifle fire (I doubt it will survive a helicopter strike), will be those cameras. The Syrian army will not need a long time to figure out that they should aim for the cameras, then run up to that thing and kill the occupants.
I don't see how it can possibly be productive to spend time flaming him and Canonical instead of using or contributing to competing systems if you dislike their products that much
There are two problems with this sentiment:
We are not in a competition. This community is supposed to be about sharing -- sharing code, sharing bandwidth, sharing disk space, etc. If we start competing like a bunch of little corporations, the whole community will fail.
Canonical has an enormous number of users; what they do with Ubuntu has far-reaching implications. If they bundle Nvidia's proprietary drivers, they are basically telling Nvidia that millions of GNU/Linux users can be Nvidia's customers without Nvidia having to change their practices or release one iota of information about their hardware. An increasing number of people now associate GNU/Linux with Ubuntu; if Canonical bundles spyware, that leaves many people associating spyware with GNU/Linux.
Canonical cannot just march in and turn the entire community upside down just to create a more business-friendly desktop distro. There are valid complaints about Canonical's approach and what effect Canonical is having on the free software / open source community.
People like me would LOVE to switch to 100% Linux, but it's missing things that Windows or Mac OSX offers
Such as? Most of the issues that face GNU/Linux today are not the fault of the OS itself, but of ISVs and hardware makers whose software/drivers are only available for one or two OSes. Hardware vendors are probably the worst offenders here, as not only will they not release drivers for the Linux kernel, but they won't even release enough information about their hardware to enable someone else to write the driver for them.
Ubuntu is doing nothing to change that situation. Bundling nVidia's drivers and bundling Broadcom's drivers only reinforces those companies' views that they can go on releasing poorly-engineered drivers for Linux and that it is OK to be tight-lipped about the details of the hardware. Ubuntu has not yet demonstrated any ability to bring the software the people want to their own distro, let alone to do so in a way that would benefit anyone else.
Yeah, they are a business. Somehow, Red Hat, a much bigger business, has done a lot more to benefit the community -- they even have a policy of committing patches upstream except in certain, very limited cases. Where Red Hat fails to stand up for the community -- like with the UEFI bootloader restrictions -- Canonical has also failed. So what exactly are they doing to help us? Ask most people what is keeping them away from GNU/Linux (if they even know what it is), and they won't tell you that it's the lack of a pretty interface, nor will they tell you that they need an easy-to-use package manager; most will talk about applications and drivers.
I'm confused, how exactly does one 'kill' Linux? I thought that one of the beautiful aspects of the GPL is its robustness.
GPLv2 is not as robust as you might think. Sure, you have to make your source code available, but that translates to nothing useful if nobody but you is capable of compiling, modifying, or debugging that code. Here is the most commonly referenced example of how the GPLv2 fails its purpose:
Exceptions should be used when you have an error that only your client code can resolve; I like to use writing to a full disk as an example. An I/O routine does not know what should be done if you try to write a full disk -- maybe your program cannot continue, maybe you can ask the user to delete some files. In most of today's programming languages, your error handling choices are:
Return an error. The client code now needs to know how to resume the disk operation, and it becomes needlessly complex if the error occurred in the middle of writing a long record.
Throw an exception. The client code still needs to know how to resume the disk operation, and on top of that, you run the risk of a double exception fault (even in Java or Python).
Set a global error flag, and hope the client checks it. The client still needs to know how to resume the operation.
There is, however, a third option that you have in Common Lisp but which could be implemented in any language: restarts. The thrower of an exception can and should be able to set "restart points," to which the catcher of the exception can transfer control flow after the error has been corrected. Thus, if you tried to write to a disk which is full, the catcher could ask the user to delete some files, then invoke the "try again" restart; the I/O routine knows how to retry the operation.
This requires an exception propagation mechanism that does not unwind the stack until some time after the exception is caught -- e.g. at the end of the exception handler. The exception handler's stack frame will need a pointer to the appropriate stack frame and return address for the case where no restarts are invoked (not hard), but otherwise the function call stack would be no different than it is now.
It could be that all those occupations are deserving of higher pay. Companies would not last long without competent workers, just like they would not last long without competent management, but the pay difference is not even close to being in proportion. Profit would be impossible if nobody was taking the time to determine what products a company makes, what services it provides, or what markets it operates in; profit would be equally impossible if nobody were taking the time to make products, provide customers with service, or actually work in those target markets.
The Morlocks need the Elois; the Elois need the Morlocks.
People might confuse you for some sort of communist if you keep talking like that...
No really, part of the issue here is that if one underpaid worker tries to demand better compensation, they'll just be replaced with someone else who doesn't mind the low compensation. People are trained from an early age to believe that janitorial work deserves low pay, and so if they are looking for a job cleaning toilets they generally expect low pay.
That's fine for vocational skills, but vocational training is not the sole purpose of our education system, nor should it be. A free society needs people who are educated in more than just their immediate vocation; we need people to learn philosophy and ethics, history, politics, etc. People need to be educated enough to call out their politicians on obvious lies, which means they need to be educated in economics, foreign affairs, and the various other things that politicians are supposed to manage for us.
We should not try to create a society where only the wealthy are sophisticated enough to be leaders, and where the poor only learn enough to do what the wealthy tell them. We should be working to break the aristocracy, not further cement it.
I get the impression he hates on Apple because it's popular to hate on them in particular
I get the impression that you hate on RMS because it is popular to hate on him.
Seriously though, why would RMS follow the crowd when it comes to which companies to criticize? He has always criticized companies for creating proprietary platforms and imposing proprietary licenses on their users, and Apple does both. In his view, Apple is the most serious offender; I disagree with him, but to claim that he is just following the crowd here is way off base.
the real problem with the "Just run Linux" solution is that non-Computer Science people want to do things like answer e-mail, write correspondence
My mother uses Fedora. She has no trouble checking her email.
and buy software from the store that has a nice, easy installer
Your point being what? There are vendors out there that make proprietary software for GNU/Linux that has binary installers. Frankly, I think the app store model has shown us that most users do not care how their software is installed, whether it be from a package manager or from an installer program.
We geeks don't have trouble with the idea of tinkering under the hood when we don't like something
Nobody has to "tinker under the hood" to use GNU/Linux.
I am driven to drinking when I think of my grandmother or father trying to use OSS for anything useful when they hit their first problem.
Really? In my experience, there is no difference between GNU/Linux, Windows, or Mac OS X here. My cousin called me the other day begging for help with her MacBook; she was utterly unable to troubleshoot it when it stopped booting up.
Freedom is nice, but when it involves having to become a computer engineer to exercise it
It does not, stop spreading FUD.
most people will take the padded handcuffs
Most people have no idea they have handcuffs on when they use their iPad; they think that it is just a different design and that there are technical reasons that some software cannot run on it. Many people will tell you that an iPad or a PS3 is not even a computer, because to them, a "computer" is something that runs the software you want to run on it.
Since I am not drinking the Apple hate-eraid, I imagine I will be modded into oblivion.
It's not about "hate," it is about Apple abusing their customers. Apple did not have to make jailbreaking the iPad so difficult, and they certainly didn't have to brick jailbroken iPhones. Apple could have just made a switch somewhere that disables the restrictions -- and then people who wanted to use apps that Apple did not approve could do so. Apple has always abused their power over what software people run on their computers, forbidding political cartoon programs, forbidding pornographic programs, forbidding their competitors' software, etc. This is not hate, it is criticism. There is a difference.
For what it's worth, I criticize Sony, Microsoft, and numerous other companies for engaging in these practices. Why should I go easier on Apple than I go on them? Why should RMS do so?
...online education is not going to solve these problems. There is limited evidence that online education is even as good as more traditional approaches to education, which are riddled with problems (beyond just what you point out).
What we really need is to change the culture that surrounds education. We need to stop making degrees the goal of education, and start making expanding a person's mind and skillset the goal.
This is a tricky thing, not much different from signed bootloaders. In theory, it can be great for users; in practice, it is likely to be exploited by people wishing to push DRM and other non-free systems on us. See:
Can we please move away from x86? That architecture is horribly outdated, loaded down with things that sort-of made sense in the 1970s. Today's x86 CPUs are just dressed up RISC machines; let's free up some of that chip space and just use RISC.
If you want to run x86 binaries, use a dynamic translation tool.
That is a matter of scale. An audio or video decoder is tiny compared to an application server (JBoss, at 80MB of code, is on the small end; Websphere is 2GB), and even audio and video decoders are rarely written in pure assembly language (and you can measure the difference between codecs that were optimized by a compiler and those that were not, even with those hand-rolled optimizations). Game engine SIMD is exactly where I said it would be: in very small functions (i.e. programs) or in inner loops.
As I said, hand-optimization scales poorly. You are talking about niche cases involving instructions that were design specifically for those cases. In the general case, where you did not receive some special set of instructions to do things for you, humans are not nearly as good as compilers, even humans who are well-versed in their machine's architecture.
The idea is to keep it simple, one statement or side effect per line of code
Except that you are then going to either (a) duplicate code or (b) have to introduce and keep track of more variables. In what way is that simple?
You are trying to write Java in non-Java different style
Perhaps I was not clear: that was a mistake that one of my students made. They did not know Java, they were still trying to learn it, and the point is that the Java style of programming is very unnatural. "Call f with 5 if x is 2 or else 10" is how the student was thinking about the program; they were forced to think about it instead as "if x is 2 call f with 5, otherwise call f with 10."
Note also that functional constructs do have some overheads that iterative-style code does not
Yes, there are limits to functional programming. There are limits to all programming paradigms, which is why languages should not force programmers to use a particular paradigm in all cases (and as it so happens, Clojure does have a loop construct). One of Java's major problems is that it really lacks support for anything other than object oriented programming, with only limited support for other paradigms or styles.
For my problems that are massively iterative (eg. some parts of graphics, numericals) this does make a difference, and the functional constructs are unnatural and used so infrequently to be useless
Perhaps so, although I suspect that in both cases object oriented programming is not universally applicable, and that you would appreciate the ability to just write a function without having to dress it up with class definitions. When I was an undergrad, I knew a lot of professors in the EE department who used Matlab to do computationally intense signal processing, and I know people in the CS department here who use Matlab for image processing work (and they would rule out both Java and any functional language for that work).
Surely new students follow the deterministic procedural code better at the start than having lots of anonymous closures popping up all over the place?
They do, but what I was saying was the Java is not an easy language to learn. Let's put it this way:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello world!"); } }
If you have never programmed before, that is an awful lot to deal with in a first program. It is certainly more to deal with than this:
(print "Hello world!")
In the Java case, most of the questions students were asking were about public, static, void, main, class, String, and then questions about function definition syntax, what "args" even is, etc. The Lisp case is far simpler and far more straightforward. I would say that it is acceptable to teach Java if all that complexity would eventually lead to simpler programs, if it was just a matter of scale, but unfortunately that is not the case; Java's syntax does little to keep complexity down, and the "everything is object oriented" approach adds a lot of complexity.
I find it interesting that you would mention closures here; in introductory Java courses, it is almost guaranteed that students will have to write at least one class definition. Do you think students have an easier time dealing with classes and objects than closures? Why even bring up anonymous closures; do you think new programmers have an easy time dealing with anonymous classes and objects (do you think we even get that far in a single semester)? My experience with teaching students how to write classes was this: it's hard for people who have never programmed before, especially when they are writing programs that are tiny and benefit little from classes. I would say that object oriented programming
A move to a higher level of abstraction that was so beneficial to software users that the entire market was upended. That is not in any way an isolated case; the history of the software industry is full of stories of good abstractions beating the competition and improving the state of the art. Abstraction is why Unix won, and the Unix abstraction was immensely beneficial to computer users.
How frequently do you spend time thinking about which registers are being used to store partial results in the programs you write? When was the last time you spent time thinking about which registers are being used by which variables, or when it would be a good time to store register contents in memory?
What about memory alignment and packing? Calling conventions? Near pointers and far pointers (OK maybe that one is a bit dated)? Most programmers do not think about these problems, because most programmers are trying to solve bigger problems and need to spend time thinking about the bigger picture. Getting mired down in low level details makes programmers less productive -- that is why we use programming languages.
So if we can have compilers that can automatically utilize multithreading, even if it is in a somewhat limited context, we should be happy. If you are happy to not be spending time thinking about padding data or allocating registers, you should be happy about automatic multithreading.
Some threading problems are hard, really hard. They aren't that common.
Which is why compilers should be handling as many threading problems as they can: so that rather than spending time and mental effort dealing with problems that are not so hard, we can spend time and mental effort on problems that compilers cannot solve for us. There is a reason that we use higher level languages, and that reason is not "laziness."
Why Java, though? What does the Java language have that other JVM languages do not? As a language, Java is pretty awful; you are stuck with a single programming paradigm even in cases where that paradigm makes no sense, you are writing enormous amounts of code to express what you are trying to do, and features that programmers in other languages take for granted are just not there (or are very limited). Meanwhile, you have Scala and Clojure on the JVM -- so why not just use these where functional approaches make sense, like for parallel algorithms?
easy to learn language
Having taught Java to novices at one time, I can tell you that this is not true. Here is a very small example of why Java is harder to learn than other languages:
Yes, they should have used the ternary operator. Why does Java even separate these? Why not just allow conditional statements to appear everything, which is what you get in Clojure (and any other Lisp, and many other programming languages that use reduction semantics)? This sort of rigid syntax makes the task of learning Java needlessly hard, because learning Java means learning how to think in a very different, very unnatural way.
Just like quicksort(3) is far faster than bubblesort so too is a highly threadable code faster than non-threadble code
First, just to be pedantic, I'll point out that quicksort is as bad as bubblesort in the worst case, to a constant factor (you should have picked heapsort or mergesort). That aside, it is worth noting (and I am somewhat bothered by this when it comes to TFA) that we still do not know if it is even possible to optimize any program by parallelizing it; see the NC-vs-P question:
Multithreading is not a magic bullet, and in all likelihood it is not generally applicable.
Languages do not, contrary to belief, express intent, the provide a strict set of instructions that the computer MUST respect
Wrong on all counts. Imperative languages are a way to convey instructions to a computer; declarative languages do not convey instructions, and programming in a declarative language requires an entirely different mode of thinking (it is closer to asking a question that giving instructions). It is also not strictly necessary for the computer to do exactly what a program expresses; there has been some work on compiler optimizations that have a (tunable) chance of not maintaining soundness.
In the end a good algorithm with no compiler help will beat optimized "dumb" code in all cases larger than "toy" (say, a few dozen "n" in Big-O notation)
If you are convinced of this, try implementing something more complex than the algorithms you see in Knuth's books; say, this:
Then ask yourself this: could the constant factors in your implementation be better? At the end of the day, big constant factors will hurt your performance so badly that you might as well have used an asymptotically worse algorithm; indeed, consider fast integer multiplication:
10000 digits are needed before that algorithm actually outperforms the asymptotically worse Toom-Cook family of algorithms. Here is an even more extreme example:
Sure, that's a better matrix multiplication algorithm in the asymptotic sense...but only for matrices that are so large that you cannot even store them on today's computers.
So really, while you are right that asymptotic improvements will always beat constant factor improvements (which is what compilers are mostly going to do for you), you are wrong to ignore the importance of constant factor improvements. In the real world, constant factors matter. In the real world, quicksort and mergesort will use asymptotically worse algorithms below a certain problem size because of constant factors. In the real world, large integer multiplication is done using Karatsuba or Toom-Cook methods, not FFT methods, because of constant factors. In the real world, if you are not using a compiler to optimize your code, your code is going to be slower than it needs to be, even if you spent hours hand-tuning it, unless you are only dealing with toy problems.
Let me repeat myself: except for very small programs or very short inner loop bodies. Most of what you are describing is pretty small in terms of the amount of code and its complexity; hand-optimizing assembly code does not scale up.
Even the best of C or C++ compilers are terrible at vectorization of code.
Yeah, and the best humans are terrible at allocating registers -- so bad, in fact, that the best C compilers ignore the register keyword. What do you think is more relevant to the general case: vectorizing multimedia operations, or allocating registers? Compilers are also better than humans at:
Finding redundant or unreachable code
Finding dead or otherwise unneeded variables
Finding algebraic reductions
Strength reducing transformations
Boolean optimizations
Reducing program size
...and numerous other optimizations that, like register allocation, are more generally applicable than SIMD. There has also been work on compiler optimizations that are utterly out of reach for even the most skilled humans, like probabilistic optimizations that have a negligible (with respect to some tunable parameter) probability of being unsound.
To put it another way, look at the Orbitz story, which is over a decade old now:
On the one hand, you have hand-tuned assembly language. On the other, you have a program written in Lisp (a high level, compiled language) with some C++ mixed in (for managing memory). Orbitz was able to compete on speed, but more importantly, it was returning better results. It's not that the people who wrote that mainframe assembly language were idiots -- they were taking advantage of all sorts of special hardware features, they knew how to hack their machines better than anyone else -- it is just that the Orbitz algorithm was far too complex for efficient hand-rolled assembly code, at which point compilers are really the only choice. The mainframe guys were busy thinking about how to make use of special machine features in assembly language; the ITA team was busy solving the higher-level problem, and relying on their compiler to generate good assembly language code. This is a particularly telling line:
We disassemble most every Lisp function looking for inefficiencies and have had both CMUCL and Franz enhanced to compile our code better.
[emphasis mine]. They disassembled their code...and then improved their compiler when they saw problems. They did not hand-roll the code, they made the compiler do a better job of generating code. These are not lazy programmers, nor are they programmers who do not know how to use assembly language; they are programmers who understand that they have a tool that is far better at generating assembly language than they are, and that they have more important things to do with their time.
I deal with quite a bit of crypto code in my work. I have seen lots of hand-tuned assembly language, I dealt with code that took advantage of the AESNI instructions to perform very fast encryption. I am well aware that in small, highly specialized functions (like AES), humans are better able to utilize special instructions to improve performance. Those are niche cases, and the techniques used in those cases have very limited applicability (even SSE is fairly limited in its applicability, by comparison with the sort of code programmers write and maintain every day), and the techniques scale very poorly.
In functional algorithms and data structures, everything is immutable (in theory) -- rather than thinking in terms of "final," think in terms of Java's String class. If you want to change one character in a String instance, you must create a new String instance. For a less trivial example, consider how a functional algorithm that removes an element from a list would work (written in Java-like syntax):
Notice that this constructs an entirely new list, even if none of the elements in the list pass the test. This may seem like a terrible idea, but let's put it this way: if you have 10 threads that share the list, and one of them wants to remove some nodes, you would have had to have copied the list anyway; the functional approach to remove_if is exactly what you want. Now, consider this function, which only removes the first node to match:
Now you have a situation where lists share nodes -- and again, imagine a situation where 10 threads share the list, and one wants to perform this operation. This is one of the reasons that functional programming is so promising for parallel algorithms: you have fewer situations where explicit mutexes are needed, because you are usually copying things that you intend to modify (or more precisely, you never really modify anything).
Of course, things are more complicated in the real world. Purely functional approaches would obviously be pretty inefficient in a lot of cases, since things would be needlessly copied. Lisp, as an example, has both a non-destructive append as well as a destructive nconc, the latter being intended for use in situations where the original lists will not be used again (and can therefore be modified).
How about we write new code in a functional language, instead of clinging to imperative languages? Put C, C++, and Java in the category they belong in: maintenance and legacy code only.
Or, gawd forbid.. we could teach programmers how to use threading?
No, we want our compilers to do these things for us, because things that compilers can do they usually do better than humans can. Once your programs become large enough and complex enough, compilers outperform humans every time -- it's not about laziness, it is about the limits of human programming ability.
Compilers surpassed humans when it comes to optimization a very long time ago, except for very small programs or very short inner loop bodies.
I have tried blinding cameras with lasers. It's hard.
It's not hard, however, to shoot something the size of a camera from 100 yards away using a hunting rifle. I suspect that the weakness of this vehicle, assuming that the rusty armor can withstand assault rifle fire (I doubt it will survive a helicopter strike), will be those cameras. The Syrian army will not need a long time to figure out that they should aim for the cameras, then run up to that thing and kill the occupants.
Or they could just fire an RPG at it.
I don't see how it can possibly be productive to spend time flaming him and Canonical instead of using or contributing to competing systems if you dislike their products that much
There are two problems with this sentiment:
Canonical cannot just march in and turn the entire community upside down just to create a more business-friendly desktop distro. There are valid complaints about Canonical's approach and what effect Canonical is having on the free software / open source community.
People like me would LOVE to switch to 100% Linux, but it's missing things that Windows or Mac OSX offers
Such as? Most of the issues that face GNU/Linux today are not the fault of the OS itself, but of ISVs and hardware makers whose software/drivers are only available for one or two OSes. Hardware vendors are probably the worst offenders here, as not only will they not release drivers for the Linux kernel, but they won't even release enough information about their hardware to enable someone else to write the driver for them.
Ubuntu is doing nothing to change that situation. Bundling nVidia's drivers and bundling Broadcom's drivers only reinforces those companies' views that they can go on releasing poorly-engineered drivers for Linux and that it is OK to be tight-lipped about the details of the hardware. Ubuntu has not yet demonstrated any ability to bring the software the people want to their own distro, let alone to do so in a way that would benefit anyone else.
Yeah, they are a business. Somehow, Red Hat, a much bigger business, has done a lot more to benefit the community -- they even have a policy of committing patches upstream except in certain, very limited cases. Where Red Hat fails to stand up for the community -- like with the UEFI bootloader restrictions -- Canonical has also failed. So what exactly are they doing to help us? Ask most people what is keeping them away from GNU/Linux (if they even know what it is), and they won't tell you that it's the lack of a pretty interface, nor will they tell you that they need an easy-to-use package manager; most will talk about applications and drivers.
I'm confused, how exactly does one 'kill' Linux? I thought that one of the beautiful aspects of the GPL is its robustness.
GPLv2 is not as robust as you might think. Sure, you have to make your source code available, but that translates to nothing useful if nobody but you is capable of compiling, modifying, or debugging that code. Here is the most commonly referenced example of how the GPLv2 fails its purpose:
https://en.wikipedia.org/wiki/TiVO
GPLv3 closes this loophole, but there are likely further loopholes that could be exploited.
Exceptions should NOT be used for 'normal' errors
Exceptions should be used when you have an error that only your client code can resolve; I like to use writing to a full disk as an example. An I/O routine does not know what should be done if you try to write a full disk -- maybe your program cannot continue, maybe you can ask the user to delete some files. In most of today's programming languages, your error handling choices are:
There is, however, a third option that you have in Common Lisp but which could be implemented in any language: restarts. The thrower of an exception can and should be able to set "restart points," to which the catcher of the exception can transfer control flow after the error has been corrected. Thus, if you tried to write to a disk which is full, the catcher could ask the user to delete some files, then invoke the "try again" restart; the I/O routine knows how to retry the operation.
This requires an exception propagation mechanism that does not unwind the stack until some time after the exception is caught -- e.g. at the end of the exception handler. The exception handler's stack frame will need a pointer to the appropriate stack frame and return address for the case where no restarts are invoked (not hard), but otherwise the function call stack would be no different than it is now.
It could be that all those occupations are deserving of higher pay. Companies would not last long without competent workers, just like they would not last long without competent management, but the pay difference is not even close to being in proportion. Profit would be impossible if nobody was taking the time to determine what products a company makes, what services it provides, or what markets it operates in; profit would be equally impossible if nobody were taking the time to make products, provide customers with service, or actually work in those target markets.
The Morlocks need the Elois; the Elois need the Morlocks.
People might confuse you for some sort of communist if you keep talking like that...
No really, part of the issue here is that if one underpaid worker tries to demand better compensation, they'll just be replaced with someone else who doesn't mind the low compensation. People are trained from an early age to believe that janitorial work deserves low pay, and so if they are looking for a job cleaning toilets they generally expect low pay.
That's fine for vocational skills, but vocational training is not the sole purpose of our education system, nor should it be. A free society needs people who are educated in more than just their immediate vocation; we need people to learn philosophy and ethics, history, politics, etc. People need to be educated enough to call out their politicians on obvious lies, which means they need to be educated in economics, foreign affairs, and the various other things that politicians are supposed to manage for us.
We should not try to create a society where only the wealthy are sophisticated enough to be leaders, and where the poor only learn enough to do what the wealthy tell them. We should be working to break the aristocracy, not further cement it.
I get the impression he hates on Apple because it's popular to hate on them in particular
I get the impression that you hate on RMS because it is popular to hate on him.
Seriously though, why would RMS follow the crowd when it comes to which companies to criticize? He has always criticized companies for creating proprietary platforms and imposing proprietary licenses on their users, and Apple does both. In his view, Apple is the most serious offender; I disagree with him, but to claim that he is just following the crowd here is way off base.
the real problem with the "Just run Linux" solution is that non-Computer Science people want to do things like answer e-mail, write correspondence
My mother uses Fedora. She has no trouble checking her email.
and buy software from the store that has a nice, easy installer
Your point being what? There are vendors out there that make proprietary software for GNU/Linux that has binary installers. Frankly, I think the app store model has shown us that most users do not care how their software is installed, whether it be from a package manager or from an installer program.
We geeks don't have trouble with the idea of tinkering under the hood when we don't like something
Nobody has to "tinker under the hood" to use GNU/Linux.
I am driven to drinking when I think of my grandmother or father trying to use OSS for anything useful when they hit their first problem.
Really? In my experience, there is no difference between GNU/Linux, Windows, or Mac OS X here. My cousin called me the other day begging for help with her MacBook; she was utterly unable to troubleshoot it when it stopped booting up.
Freedom is nice, but when it involves having to become a computer engineer to exercise it
It does not, stop spreading FUD.
most people will take the padded handcuffs
Most people have no idea they have handcuffs on when they use their iPad; they think that it is just a different design and that there are technical reasons that some software cannot run on it. Many people will tell you that an iPad or a PS3 is not even a computer, because to them, a "computer" is something that runs the software you want to run on it.
Since I am not drinking the Apple hate-eraid, I imagine I will be modded into oblivion.
It's not about "hate," it is about Apple abusing their customers. Apple did not have to make jailbreaking the iPad so difficult, and they certainly didn't have to brick jailbroken iPhones. Apple could have just made a switch somewhere that disables the restrictions -- and then people who wanted to use apps that Apple did not approve could do so. Apple has always abused their power over what software people run on their computers, forbidding political cartoon programs, forbidding pornographic programs, forbidding their competitors' software, etc. This is not hate, it is criticism. There is a difference.
For what it's worth, I criticize Sony, Microsoft, and numerous other companies for engaging in these practices. Why should I go easier on Apple than I go on them? Why should RMS do so?
...online education is not going to solve these problems. There is limited evidence that online education is even as good as more traditional approaches to education, which are riddled with problems (beyond just what you point out).
What we really need is to change the culture that surrounds education. We need to stop making degrees the goal of education, and start making expanding a person's mind and skillset the goal.
Unlikely. See: number of people who stopped bothering with PGP because they wanted to use GMail to check their mail from wherever.
This is a tricky thing, not much different from signed bootloaders. In theory, it can be great for users; in practice, it is likely to be exploited by people wishing to push DRM and other non-free systems on us. See:
https://en.wikipedia.org/wiki/Bus_encryption
Can we please move away from x86? That architecture is horribly outdated, loaded down with things that sort-of made sense in the 1970s. Today's x86 CPUs are just dressed up RISC machines; let's free up some of that chip space and just use RISC.
If you want to run x86 binaries, use a dynamic translation tool.
That is a matter of scale. An audio or video decoder is tiny compared to an application server (JBoss, at 80MB of code, is on the small end; Websphere is 2GB), and even audio and video decoders are rarely written in pure assembly language (and you can measure the difference between codecs that were optimized by a compiler and those that were not, even with those hand-rolled optimizations). Game engine SIMD is exactly where I said it would be: in very small functions (i.e. programs) or in inner loops.
As I said, hand-optimization scales poorly. You are talking about niche cases involving instructions that were design specifically for those cases. In the general case, where you did not receive some special set of instructions to do things for you, humans are not nearly as good as compilers, even humans who are well-versed in their machine's architecture.
So in Java, a very simple List class following this definition would be:
Another way to put it is this: the only value that represents "one list" is null.
The idea is to keep it simple, one statement or side effect per line of code
Except that you are then going to either (a) duplicate code or (b) have to introduce and keep track of more variables. In what way is that simple?
You are trying to write Java in non-Java different style
Perhaps I was not clear: that was a mistake that one of my students made. They did not know Java, they were still trying to learn it, and the point is that the Java style of programming is very unnatural. "Call f with 5 if x is 2 or else 10" is how the student was thinking about the program; they were forced to think about it instead as "if x is 2 call f with 5, otherwise call f with 10."
Note also that functional constructs do have some overheads that iterative-style code does not
Yes, there are limits to functional programming. There are limits to all programming paradigms, which is why languages should not force programmers to use a particular paradigm in all cases (and as it so happens, Clojure does have a loop construct). One of Java's major problems is that it really lacks support for anything other than object oriented programming, with only limited support for other paradigms or styles.
For my problems that are massively iterative (eg. some parts of graphics, numericals) this does make a difference, and the functional constructs are unnatural and used so infrequently to be useless
Perhaps so, although I suspect that in both cases object oriented programming is not universally applicable, and that you would appreciate the ability to just write a function without having to dress it up with class definitions. When I was an undergrad, I knew a lot of professors in the EE department who used Matlab to do computationally intense signal processing, and I know people in the CS department here who use Matlab for image processing work (and they would rule out both Java and any functional language for that work).
Surely new students follow the deterministic procedural code better at the start than having lots of anonymous closures popping up all over the place?
They do, but what I was saying was the Java is not an easy language to learn. Let's put it this way:
If you have never programmed before, that is an awful lot to deal with in a first program. It is certainly more to deal with than this:
In the Java case, most of the questions students were asking were about public, static, void, main, class, String, and then questions about function definition syntax, what "args" even is, etc. The Lisp case is far simpler and far more straightforward. I would say that it is acceptable to teach Java if all that complexity would eventually lead to simpler programs, if it was just a matter of scale, but unfortunately that is not the case; Java's syntax does little to keep complexity down, and the "everything is object oriented" approach adds a lot of complexity.
I find it interesting that you would mention closures here; in introductory Java courses, it is almost guaranteed that students will have to write at least one class definition. Do you think students have an easier time dealing with classes and objects than closures? Why even bring up anonymous closures; do you think new programmers have an easy time dealing with anonymous classes and objects (do you think we even get that far in a single semester)? My experience with teaching students how to write classes was this: it's hard for people who have never programmed before, especially when they are writing programs that are tiny and benefit little from classes. I would say that object oriented programming
All the performance gains are immediately devoured to make life easier for developers with no benefit to users.
Nonsense:
http://www.paulgraham.com/carl.html
A move to a higher level of abstraction that was so beneficial to software users that the entire market was upended. That is not in any way an isolated case; the history of the software industry is full of stories of good abstractions beating the competition and improving the state of the art. Abstraction is why Unix won, and the Unix abstraction was immensely beneficial to computer users.
How frequently do you spend time thinking about which registers are being used to store partial results in the programs you write? When was the last time you spent time thinking about which registers are being used by which variables, or when it would be a good time to store register contents in memory?
What about memory alignment and packing? Calling conventions? Near pointers and far pointers (OK maybe that one is a bit dated)? Most programmers do not think about these problems, because most programmers are trying to solve bigger problems and need to spend time thinking about the bigger picture. Getting mired down in low level details makes programmers less productive -- that is why we use programming languages.
So if we can have compilers that can automatically utilize multithreading, even if it is in a somewhat limited context, we should be happy. If you are happy to not be spending time thinking about padding data or allocating registers, you should be happy about automatic multithreading.
Some threading problems are hard, really hard. They aren't that common.
Which is why compilers should be handling as many threading problems as they can: so that rather than spending time and mental effort dealing with problems that are not so hard, we can spend time and mental effort on problems that compilers cannot solve for us. There is a reason that we use higher level languages, and that reason is not "laziness."
easy to learn language
Having taught Java to novices at one time, I can tell you that this is not true. Here is a very small example of why Java is harder to learn than other languages:
Yes, they should have used the ternary operator. Why does Java even separate these? Why not just allow conditional statements to appear everything, which is what you get in Clojure (and any other Lisp, and many other programming languages that use reduction semantics)? This sort of rigid syntax makes the task of learning Java needlessly hard, because learning Java means learning how to think in a very different, very unnatural way.
Just like quicksort(3) is far faster than bubblesort so too is a highly threadable code faster than non-threadble code
First, just to be pedantic, I'll point out that quicksort is as bad as bubblesort in the worst case, to a constant factor (you should have picked heapsort or mergesort). That aside, it is worth noting (and I am somewhat bothered by this when it comes to TFA) that we still do not know if it is even possible to optimize any program by parallelizing it; see the NC-vs-P question:
https://en.wikipedia.org/wiki/P-complete
Multithreading is not a magic bullet, and in all likelihood it is not generally applicable.
Languages do not, contrary to belief, express intent, the provide a strict set of instructions that the computer MUST respect
Wrong on all counts. Imperative languages are a way to convey instructions to a computer; declarative languages do not convey instructions, and programming in a declarative language requires an entirely different mode of thinking (it is closer to asking a question that giving instructions). It is also not strictly necessary for the computer to do exactly what a program expresses; there has been some work on compiler optimizations that have a (tunable) chance of not maintaining soundness.
In the end a good algorithm with no compiler help will beat optimized "dumb" code in all cases larger than "toy" (say, a few dozen "n" in Big-O notation)
If you are convinced of this, try implementing something more complex than the algorithms you see in Knuth's books; say, this:
http://eurocrypt2010rump.cr.yp.to/9854ad3cab48983f7c2c5a2258e27717.pdf
Then ask yourself this: could the constant factors in your implementation be better? At the end of the day, big constant factors will hurt your performance so badly that you might as well have used an asymptotically worse algorithm; indeed, consider fast integer multiplication:
https://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm
10000 digits are needed before that algorithm actually outperforms the asymptotically worse Toom-Cook family of algorithms. Here is an even more extreme example:
https://en.wikipedia.org/wiki/Coppersmith%E2%80%93Winograd_algorithm
Sure, that's a better matrix multiplication algorithm in the asymptotic sense...but only for matrices that are so large that you cannot even store them on today's computers.
So really, while you are right that asymptotic improvements will always beat constant factor improvements (which is what compilers are mostly going to do for you), you are wrong to ignore the importance of constant factor improvements. In the real world, constant factors matter. In the real world, quicksort and mergesort will use asymptotically worse algorithms below a certain problem size because of constant factors. In the real world, large integer multiplication is done using Karatsuba or Toom-Cook methods, not FFT methods, because of constant factors. In the real world, if you are not using a compiler to optimize your code, your code is going to be slower than it needs to be, even if you spent hours hand-tuning it, unless you are only dealing with toy problems.
Even the best of C or C++ compilers are terrible at vectorization of code.
Yeah, and the best humans are terrible at allocating registers -- so bad, in fact, that the best C compilers ignore the register keyword. What do you think is more relevant to the general case: vectorizing multimedia operations, or allocating registers? Compilers are also better than humans at:
To put it another way, look at the Orbitz story, which is over a decade old now:
http://www.paulgraham.com/carl.html
On the one hand, you have hand-tuned assembly language. On the other, you have a program written in Lisp (a high level, compiled language) with some C++ mixed in (for managing memory). Orbitz was able to compete on speed, but more importantly, it was returning better results. It's not that the people who wrote that mainframe assembly language were idiots -- they were taking advantage of all sorts of special hardware features, they knew how to hack their machines better than anyone else -- it is just that the Orbitz algorithm was far too complex for efficient hand-rolled assembly code, at which point compilers are really the only choice. The mainframe guys were busy thinking about how to make use of special machine features in assembly language; the ITA team was busy solving the higher-level problem, and relying on their compiler to generate good assembly language code. This is a particularly telling line:
We disassemble most every Lisp function looking for inefficiencies and have had both CMUCL and Franz enhanced to compile our code better.
[emphasis mine]. They disassembled their code...and then improved their compiler when they saw problems. They did not hand-roll the code, they made the compiler do a better job of generating code. These are not lazy programmers, nor are they programmers who do not know how to use assembly language; they are programmers who understand that they have a tool that is far better at generating assembly language than they are, and that they have more important things to do with their time.
I deal with quite a bit of crypto code in my work. I have seen lots of hand-tuned assembly language, I dealt with code that took advantage of the AESNI instructions to perform very fast encryption. I am well aware that in small, highly specialized functions (like AES), humans are better able to utilize special instructions to improve performance. Those are niche cases, and the techniques used in those cases have very limited applicability (even SSE is fairly limited in its applicability, by comparison with the sort of code programmers write and maintain every day), and the techniques scale very poorly.
Notice that this constructs an entirely new list, even if none of the elements in the list pass the test. This may seem like a terrible idea, but let's put it this way: if you have 10 threads that share the list, and one of them wants to remove some nodes, you would have had to have copied the list anyway; the functional approach to remove_if is exactly what you want. Now, consider this function, which only removes the first node to match:
Now you have a situation where lists share nodes -- and again, imagine a situation where 10 threads share the list, and one wants to perform this operation. This is one of the reasons that functional programming is so promising for parallel algorithms: you have fewer situations where explicit mutexes are needed, because you are usually copying things that you intend to modify (or more precisely, you never really modify anything).
Of course, things are more complicated in the real world. Purely functional approaches would obviously be pretty inefficient in a lot of cases, since things would be needlessly copied. Lisp, as an example, has both a non-destructive append as well as a destructive nconc, the latter being intended for use in situations where the original lists will not be used again (and can therefore be modified).
How about we write new code in a functional language, instead of clinging to imperative languages? Put C, C++, and Java in the category they belong in: maintenance and legacy code only.
Or, gawd forbid.. we could teach programmers how to use threading?
No, we want our compilers to do these things for us, because things that compilers can do they usually do better than humans can. Once your programs become large enough and complex enough, compilers outperform humans every time -- it's not about laziness, it is about the limits of human programming ability.
Compilers surpassed humans when it comes to optimization a very long time ago, except for very small programs or very short inner loop bodies.