Hacker News new | past | comments | ask | show | jobs | submit login
How I grew to hate every computer language (lbrandy.com)
44 points by cruise02 on Aug 17, 2009 | hide | past | favorite | 42 comments



I went through a similar progression. Then I learned SML. I haven't started hating it yet, and it's been about 6 years. YMMV, but I generally find that the things I hated most about most "main stream" programming languages are absent in languages like ML and Haskell (and I assume in F# too, though I haven't really used it).


Would vote this up 10 million times, if I could.

This is because the structures of ML and Haskell are based on the structure of logical proof, through the Curry-Howard isomorphism. Most programming languages are constructed on top of arbitrary decisions made by their designers.


True.

And in particular, there are a few things I really like:

Hindley Milner-style type systems make life easier. You don't write out very many type annotations, but you get a type safety guarantee. People seem to underestimate just how strong this guarantee really is. It is equivalent to "Your program will not crash" for all intents and purposes. Similarly, I generally find that a program that passes type checking is about 7 trillion* times more likely to be functionally correct than a Java or C++ program that merely compiles.

(Specific to ML) The "Mostly functional" nature of SML means that you usually write pure functional programs. However, it's easy to drop down into something resembling a more imperative style of programming if you need to. I found this helped my learning curve a lot. I could write functional code as far as my limited experience would allow me, and then I could finish the program using my (considerably more extensive) imperative programming experience. I've found that I had done this less and less as I've become more experienced (to the point where I pretty much don't do it at all), but it was a nice option. Supplementary to this point, the presence of mutable arrays occasionally makes sense in terms of performance, and so these are available to you in the rare cases where it makes sense to use them. This certainly isn't knocking purely functional languages such as Haskell that use Monads to achieve much the same effect, I've just found that having a "mostly-functional" approach has suited my brain, and permitted me to write more efficient programs with less effort. Others would probably say exactly the opposite with regards to Haskell vs ML.

Pattern matching. Oh, how I love thee, especially when combined with recursive data types. I don't like to get sentimental about programming languages, but seriously, sometimes it is pure poetry.

Functors give you most of the nice properties of templates in C++ without the warts (at least with respect to the way I use each).

The performance of compiled OCaml and SML code is very similar to that of C++ by some benchmarks. In practice, I've found this to mean "plenty fast enough", even in scientific and numerical computing applications.

Polymorphism and higher-order functions make code re-use a practical reality, as in, you usually write things in a reusable way purely by accident rather than needing to think about how you will make things reusable.

Sorry, this is turning into a love letter, so I'll stop.

* May or may not be the exact figure. I mean "a lot".


I've been really enjoying learning Haskell. I believe I'm still in a honeymoon phase though, and it too will pass, though it has lasted longer than for any other language.


These kinds of posts have never really resonated with me. I know about a dozen different languages and use 3 of them 99% of the time. They all have their pros and cons.

I may be in the minority here, but I've never really cared as much about the language as the task at hand. Sure, some languages are better than others for different things, but you can do almost anything with almost any language. I'm so concerned about getting the result to the customer that I forget how much less I'd be suffering with different tools.

Now if there were an article entitled, "How I grew to hate every practitioner of computer languages," that might be a different story :-) I've seen great code and horrible code in every language. I'll take great programming in a crappy language over crappy programming in a great language any day.


A great language will make crappy programming harder.


Is that necessarily a good thing? Surely then it's harder to decide who is a good programmer and who is not.


I never said that a good programming language will make a bad programmer write good code, just that it makes crappy programming harder, eg by providing you with a choice of tools and constructs so that you can choose what makes sense for the task, instead of having to force some language feature to do something it really isn't suited for.

If you have nice language features for the various tasks which you are trying to achieve, then the code will be better than if you don't. If these features are designed in a way that promotes good, clean, reusable and easy to understand code, then it makes crappy programming harder.

Bad programmers will always write bad code and good programmers should always be able to write good code. A good language doesn't get in your way, it helps you and so a good programmer can write great code with the same amount of effort as a good programmer writes good code in a lesser language.


Who cares who's a good programmer and who's not? What matters is what gets made, and if people are making cool stuff then I don't care if they're completely inept. Hell, I'm completely inept and I've found it doesn't matter as long as I end up with a product people want to use.


Who cares who's a good programmer and who's not?

The poor soul who has to maintain your crap.

it doesn't matter as long as I end up with a product people want to use

It does matter when it comes to maintaining that code base. When maintaining crappy code, only bad things can happen:

  1. It takes too long.
  2. It costs too much.
  3. It doesn't get done at all.
"cool stuff" and "completely inept" are contradictory terms.

You may not care, but enough of us do that you should get better at your craft and spare the rest of us.


Well, if the code thats produced is good, then I agree with unalone - it doesn't matter if the programmer is good or not.

Of course, if the code IS bad, then sure, but would that not kinda go against what I was saying in my comment? Its all about solving a problem in the simplest, cleanest, most complete (ie, the problem isn't solved when corner cases are ignored) way. If a language is truely good, it will help programmers, good and bad, to achieve this. If the bad programmer then manages to produce good code, then (s)he is indistinguishable from a good programmer. (The difference between the two then becomes that the good programmer can do this with most problems, while the bad one with only a subset).


You're making the assumption that I code things that require maintenance from other people, and that I code for a living. I code for fun, and I make small things that other people happen to enjoy, things simple enough that once I get them working the first time, they don't break. When I work on major projects, my partner's the programmer, not me.


Language designers want to create languages that professionals will use. Maintenance is a problem for any professional. You're lucky not to have to deal with that problem but that doesn't mean language designers are mistaken for engaging in attempting to find a solution to that problem just because it doesn't affect you.


Please let me answer you in one thread before you repeat your counterargument. I've answered this as you posted this second one.


Yes, ease of programmer ability ascertainment should not be a concern of a PL but I don't support your "as long as I end up with a product people want to use" philosophy that belittles the importance of the means used to reach an end. When discussing PLs you are discussing means. If you don't care then I don't understand your interest in this post.


I wasn't saying that programming language doesn't matter. I was saying, in regards to axod's specific point that "great languages make it harder to write crappy code" might make it harder to decide who's good and who's not, that the goal of a programming language isn't to let people judge other programmers. It's to let them write code.


Only true if, by harder, you mean relative to the good practise that it makes easy.


I definitely agree. My comment was vague (and was meant as joking stab at the parent). A good language will aid the programmer with whatever task the language was designed for. A text processing language will make writing bad crappy text processing code harder compared to writing good text processing code. That doesn't mean that writing, eg, a GUI in this language will be easy, however.


I agree, but I did have an intense moment with Fortran II that effectively launched me into a compiler-writing career.

And actually a second point was a zero-knowledge dislike of COBOL. This faded when after a couple years of RPG-III, a COBOL compiler was installed. Felt so much better.


Good engineers don't see problems or solutions, only trade-offs.


That's certainly one platitude that contains some of the same keywords as the article.

Except that programmers work in a synthetic world. We shouldn't have to "trade off" (nor should we find this acceptable) unless we actually encounter some limitation from the real world (e.g. finiteness of computer memory or CPU cycles, or developer time). I would argue that most of the time, we are tilting at windmills instead of solving things the way would we like to solve them.


Of course programming languages involve trade-offs. Concrete syntax trade-offs abound, but more important are semantic trade-offs. Many are of the form feature vs. performance. Dispatch? Memory safety? Laziness? Otherss are more complicated, like those involving type systems, which are formally complex while affecting the informal "feel" of the language.

I think it's specious to suggest that the problems in programming language design and implementation are illusionary, and that we could somehow code "the way would we [sic] like". The language of computation is extremely subtle, and the process of building abstractions over our computers' basic operations is still more subtle. We are not done exploring possibilities---nor, I suspect, will we ever be.


> I think it's specious to suggest that the problems in programming language design and implementation are illusionary

That's definitely not what I was trying to suggest. I was suggesting that we do not need to accept "trade-offs" as an inherent property of programming, and that we can strive to do better. Sure, programming languages are designed within a context, but the number of inherent limitations upon us as programming language designers are fewer than those placed on real-world engineers. Gravity, mass, cost and tensile strength of certain materials are fixed constants, yet building skyscrapers and wide-body jets are a practical reality. What have we got to contend with? Incompleteness? Bah!

So my reply was not intended to say "programming language design is not hard", rather, "we should not be so quick to accept unnecessary trade-offs". The original post was complaining about problems which have been (largely) solved in other languages. The reply about seeing trade-offs implied that working around limitations is acceptable and part of an engineer's lot. I disagreed, suggesting that most of these "limitations" are imposed by limitations of thought, not limitations in what we can actually achieve.


The best languages for writing quick-and-dirty 15-minute scripts are never going to be the best languages for million-line, mission-critical applications, the best languages for embedded programming are not going to be the best languages for web programming, and the best languages for beginners are not going to be the best languages for more advanced programmers.

So perhaps programmers sometimes give up too quickly and could do better on all those fronts, but it's not some limitation of the real world that forces the tradeoff: it's the fact that different decisions regarding things like syntax or the type system do have a real impact on the suitability of the language for different purposes, and you can't be all things to all people there. Sometimes you want a very loose language that doesn't get in your way; sometimes you want a very strict language that ensures correctness; sometimes you want a language that lets you manipulate things close to the metal; sometimes you want a very simple language that's easy to learn because it doesn't have too many concepts; sometimes you want a very advanced language that gives you lots of different ways to solve problems.

No language can or should be all things to all people.


You say that, but people have written 50,000-line Tcl scripts for controlling oil rigs...


Of course . . . you can also use a flat rock to hammer in nails when framing a house, but a framing hammer might be a better idea. Doesn't mean it can't be done, though, especially if you're really good with rocks and already have them lying around, whereas you'd have to go to the hardware store just to buy the framing hammer.

My point was not "language X can't do project type Y," but rather that the things that put a language in the sweet spot for certain types of projects kind of inevitably pull it out of the sweet spot for other types of projects. I.e. it really is always about trade-offs. Sometimes the mere fact that you know how to use a given language is enough of a win to outweigh any potential benefits of switching to another language.


While I'm not a big fan of Tcl/Tk, I'm quite familiar with it and find I this statement confused or misleading in at least two ways:

First, GWL once told me the bulk of the code is actually rather mundane GUI form definitions (the sort of crap that is trivial to generate with high level interface tools). There's only a small amount of actual "logic" at that level that ever needs to be maintained (the real control isn't done in Tcl).

Second, even if there are 50,000 lines of Tcl (actually I think the actual number is closer to 300,000), it doesn't mean it's one big script. It's probably more fair to compare it to a unix system with hundreds or thousands of separate smaller write-once scripts.

Ironically I think the real fault here lies with GWL and other Tcl enthusiasts for quoting a true but misleading "number of lines" in the first place. The number of separate scripts and average script length would be more meaningful and representative of the system's real complexity.


To an extent I agree.

The general purpose language has been very successful because there's sufficient commonality between the operations that a lot of programs enact (what is good for one is good for the other) but the DSL has been also, perhaps a lesser extent, because of the benefits of specific optimisations you mention.

That's my balanced observation.


Exactly:

"If I wanted to put an 'If' statement in a 'While' statement, I don't have to worry about whether the 'If' statement will oscillate at a certain frequency and rub against the 'While' statement and eventually they will fracture. I don't have to worry whether it will oscillate at a certain higher frequency and induce a signal in the value of some other variable. I don't have to worry about how much current that 'If' statement will draw and whether it can dissipate the heat there inside that while statement. Whether there will be a voltage drop across the while statement that will make the 'If' statement not function. I don't have to worry that if i run this program in a salt water environment that the salt water may get in between the 'If' statement and the 'While' statement and cause corrosion. I don't have to worry when I refer to the value of a variable whether I am exceeding the fan-out limit by referring to it 20 times. I don't have to worry, when I refer to the variable, how much capacitance it has and whether there has been sufficient time to charge up the value. I don't have to worry when I write the program, about how I am going to physically assemble each copy and whether I can manage to get access to put that 'If' statement inside the 'While' statement. I don't have to worry about how I am going to gain access in case that 'If' statement breaks, to remove it and replace it with a new one. So many problems that we don't have to worry about in software. That makes it fundamentally easier. It is fundamentally easier to write a program than to design a physical object that's going to work. This may seem strange because you have probably heard people talking about how hard software is to design and how this is a big problem and how we are going to solve it. They are not really talking about the same question as I am. I am comparing physical and software systems of the same complexity, the same number of parts. I am saying the software system is much easier to design than the physical system. But the intelligence of people in these various fields is the same, so what do we do when we are confronted with an easy field? We just push it further! We push our abilities to the limit. If systems of the same size are easy, let's make systems which are ten times as big, then it will be hard! That's what we do! We make software systems which are far bigger in terms of number of parts than physical systems. A physical system whose design has a million different pieces in it is a mega project. A computer program whose design has a million pieces in it, is maybe 300,000 lines, a few people will write that in a couple of years."

"The Danger of Software Patents" by Richard M. Stallman (http://www.cl.cam.ac.uk/~mgk25/stallman-patents.html)


I wonder when it is you don't encounter limitations from the real world. I certainly couldn't type a line of code without my computer interacting with the real-world.


If by "real-world" you mean "sending signals to a display within certain timing constraints", sure.

My point is that software is inherently virtual, therefore there are far fewer constraints placed on its shape, size and smell than any similarly elaborate construction in the real world. For example, if I want two cogs to interact with each other in the real world, they have to be physically adjacent. If I want to things to interact in software, I just say so and it is done.

And that is what gives programming language designers the freedom to do a much better job. Most of the languages in common use today are the way they are because they are essentially exposing an underlying architecture with some syntax over the top, or doing the same at one degree removed. Just because we've always done things in a particular way doesn't mean that we need to keep doing them that way.

Which goes back to my original point that we have essentially artificially constrained ourselves by insisting that anything we do be reasonably similar to everything we've done before.


Hubris.

Programming is partly a creative pursuit. Thus, it helps if one enjoys using the tool you need for the job.


> tool you need for the job.

What is it about your tool that you need for the job? Is your tool specifically designed for your (type of) job? What trade-offs are you making with that tool versus other tools? Did you consider the long-term implications of your choice of tool? What if you wish to extend your job? Is your tool well-maintained? What if a customer comes back with questions about your job after a few years? Is it possible that more people will work on your job? Will they need to learn your tool? Will you still be happy about your choice of tool? (etc, etc, etc)

Engineering is making trade-offs.


I find that every computer language does one thing best (ML with pattern matching, Tk with quick GUIs, Perl with text, Python with object orientation, Java with .... never mind), but in most other respects falls short of some other computer language. The more languages I know, the more salient their respective shortcomings become, which makes me hate them all. So I sympathize.


I think you've misunderstood my use of "pattern matching" in the post above. The way you've used it is a bit like saying "C is the best language for if statements".

A pattern match in ML is something like:

fun f 0 = <do something> | f 1 = <do something else> | f n = <do something in the general case

This goes really well with the ability to build up arbitrary datastructures, for example:

fun sum_tree (Node v) = v | sum_tree (Branch (left, v, right)) = v + sum_tree(left) + sum_tree(right)

Which would sum up all the values stored in an integer tree.


> Java with .... never mind

Creating jobs.


I have my favorite languages (python and C) and have gotten used to their warts. It is like a marriage, you just get used to the problems and learn to avoid the problem areas. For kicks I think assembly is still fun to program in, e.g., the Tierra assembly language that was built by Tom Ray back in the early 90s for evolution research was fun to toy with.


It feels to me that most* programming languages were created to solve a particular problem and use a particular style. If you are working in that problem domain then often that language will be best. If you are looking for a language to be your go-to for everything you're only going to end up hating them all.

Each programming language makes trade-offs. Ease of low-level control vs. ease of high-level constructs. Quick write-execute turn around vs. code optimization. Strong type guarantees vs. ease-of-use duck typing. There are hundreds of these tradeoffs and you just have to figure out where you want to be for your particular problem.

* I say most, because there are some really terrible languages out there that were largely created out of ignorance. Usually they're just scripting languages created for a specific application. Instead of using a tested solution, like extending Ruby, Perl, or Lua, they write their own which has most of the same features half-implemented.


Pity he didn't learn Lisp.


He did. Its right before Ruby and Python.


I know. I was being sarcastic.


Where's the stage when you love every language except PHP and C++, because languages are fun and enabling, and have those beauties?




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: