Tell us why your language sucks

Let’s play a game. Take your favourite languages and tell us what you hate about them. Like I’ve said before – all languages suck. Don’t pretend yours is perfect. If there aren’t things about it which annoy you you’re not trying hard enough.

Note: This should not be about bashing languages you don’t use or like, or even languages which you use and don’t like. Everyone does that already. I don’t want to hear yet another rant about why Ruby sucks from a Java programmer, why Java sucks from a Factor programmer, why Lisp sucks from a Javascript programmer, etc. I’m not even interested in hearing about people who are forced to use Java|C|C++|Javascript|Whatever and hate it. Tired, been done to death. It specifically has to be a language you use at least semi-regularly and like. Feel free to post here, to your own blogs, to the inevitable reddit thread, etc. But wherever you post it, have fun. Go on, rant. Get it off your chest. You’ll feel better for it. :-)

I’ve already started with Scala. Now I’ll do Haskell. Hopefully someone more experienced with the language will follow up, as I’ll freely admit it’s not my best language.

So, things I hate about Haskell:

Let’s start with the obvious. Monad tutorials. No, not monads. Specifically the tutorials. They’re endless, overblown and dear god are they tedious. Further, I’ve never seen any convincing evidence that they actually help. Read the class definition, write some code, get over the scary name.

Now we’ve over the one sociological issue, let’s get to some actual language ones.

Modularity. Haskell’s module system is about the minimum possible you can get away with and still claim to have a module system. Anything less and you basically have C style header files. Now, this isn’t a huge problem. To a certain degree type classes mitigate the need for anything functorial. But there are examples where it’s an issue. Take ByteStrings for example. Lazy and strict ByteStrings have essentially the same module signatures, but there’s no way to write code which is agnostic as to the type of ByteString it uses. They don’t live in a type class because it was considered that the type class signature would be too long. This is probably fair, but life would be a lot nicer if you could write functors over the ByteString modules.

In general, Haskell has very poor namespacing. If two modules define something of the same name you have to redefine one of them or refer to one of them qualified. It’s not a huge issue, especially as you *can* rename and Haskell modules are anyway not as long as Java packages. It’s not like you have to refer to M.lookup isn’t too onerous. This mainly causes problems with symbolic operators, because things like Foo.++ look a lot worse as infix operators than does. I don’t know of a good solution to this problem. Object oriented languages provide a solution to it by basically making the type of the first argument responsible for namespacing. I don’t find this especially satisfactory, but it does work.

On a similar note, Haskell type classes basically live in global scope. There are good reasons for this, and it avoids you having to write a whole lot of painful sharing constraints (The example that is thrown at me every time I complain about this is what do you do if you want to unify two Data.Sets, each of which uses a different instance of the Ord type class)? It can be a real pain though.

There’s another issue related to type classes. Let’s pick an example. Data.List defines both sortBy and sort. The difference is purely that sort uses the standard ordering on the Ord type class while sortBy uses a provided ordering. And you need to define different functions every time you want to be able to use either a type class or something user configurable. Because you can’t redefine type classes locally or pass them as first class instances there’s basically no way around this. You can normally avoid the issue with selective use of newtype and careful choice of your types, but it’s definitely there.

Which brings me to another point – type classes are not first class. The Scala encoding of type classes is clunky in many ways, but a very nice feature is that the things you’re using as type classes are real first class members of the language, and you can bring to bear all the usual tools you have for manipulating stuff.

10,000 compiler extensions. GHC introduces so many compiler extensions, and everyone goes wild about them. This is understandable. Some of them are really useful. Some of them it’s amazing to manage living without (No multiparameter type classes in H98? Yeargh. Getitaway!!). I really like most of these I’ve used, but it sometimes make it feel like you need to employ deep and profound type system voodoo to get anything done. It would be very nice to get these unified into something sane and consistent, but Haskell’ seems to have stalled.

Tuples and records. There’s basically no good generic handling for either of these. Each of the different sizes of tuples is a totally different type (with no common type classes for abstracting over them), records are just a thin wrapper over normal datatypes with no extensibility or namespacing. Your record accessors will clash just as much as any other function name.

Something which has bitten me in the past is sharing code between monadic and non-monadic contexts. You essentially need to write pure and monadic versions of a number of functions. It would be nice if generic monadic code could automagically be specialised to the identity monad in a way that didn’t uglify pure code using it, or pure code lifted to monadic versions (this is harder I think). This doesn’t come up too much, but it means that there’s often functions like foo and fooM for pure and monadic versions.

The prelude and standard type classes are a bit painful sometimes. Things which you’d expect to be overloaded into type classes aren’t (Data.Monoid defines a function mappend for example, which in the List instance is ++. Why isn’t ++ on Data.Monoid?) and sometimes the type classes which are there are poorly thought out (Num shouldn’t extend Eq, and it would be nice if + was factored out in order to provide better support for things like vector spaces). I believe there is some work on alternate numeric preludes.

Plus lots of other little things which don’t spring to mind at the moment.

Also, one final disclaimer. Please please please don’t take this as a “Haskell sucks, don’t use it!!!” post. If you do I’ll… I don’t know, give you a really devastating hurt puppy look or something.

I’d also appreciate it if you don’t use this post to start a language war. Remember – you’re only allowed to say bad things about languages you actually like. Otherwise you’re cheating. :-)

This entry was posted in programming and tagged , , on by .

57 thoughts on “Tell us why your language sucks

  1. FeepingCreature


    Crappy error messages, especially for errors in string mixins buried in nested templates.

    The lack of traced exceptions in the standard library.

    Bugs in the standard library. Seriously, it’s 2008. I shouldn’t have to worry about this sh*t.

    The Phobos/Tango schism. Still not resolved. Basically, D currently has two “standard” libraries. There was talk of getting them on a common basis, but little in the way of actual results.

    Longstanding compiler bugs. I won’t even get started on this one.

    The glacial speed of the GDC project, which provides the only free D compiler in existence.

    Eschewing language polish in 2.0 in favor of flashy features that nobody really needs (like const).

    Underpowered, half-baked tuples. They’re cool, don’t get me wrong, but they could be much more.

    A lack of mature, cross-platform, native-D GUI libraries.

    .. that’s all I can think of right now. I thought there was more ^^


  2. José Dinuncio


    It started as a nice, clean and elegant language. But it had its shortcomings. Its basic types weren’t subclasseable, no unicode, ugly __double-underscore-methods__, a tricky mechanism for setters and getters.

    Of course they worked out a lot of things. They introduced an object class, static and class methods, metaclasses, iterators and generators…

    But those are patches. The simple and elegant language design is not more.

    Hopefully, python 3000 will bring back the lost coherence.

  3. spamigator


    Lack of first-class functions (even if templates give much of the same functionality). No garbage collection. Replication of definitions in .h files. Typing system imperfect (doesn’t require casts for enums, doesn’t allow dynamic programming). Hard or impossible to mix code and data. Doesn’t scale well to increasingly common parallel systems (but virtually nothing does)

  4. John Cromartie


    The speed. I can’t wait for Ruby 1.9 to be production-ready. Ruby’s speed is rarely a limiting factor, and using an external tool to do something intense is not hard. However, it would be nice to be able to do some more intense stuff in pure Ruby.

    Rails. We all know it: Ruby is a language, Rails is a framework. But, for some reason, the majority of vocational programmers out there simply cannot separate the two in their heads. Whenever I talk about some feature of Ruby or some bit of code I wrote, coworkers scratch their heads and say something like “yeah, but why would you need that in a website?”

  5. CruxOp


    I love PHP though. I chose to use it over Ruby for greenfield development. Yet the way new releases work annoys me.

    Backwards compatibility.

    The deliberate changes are the worst. It seems that new minor revision of PHP breaks existing code. There’s a change in the return of builtin function, or a change in the flags that it can accept.

    Why break BC? Why?! I’d understand if it the break came with significant advantages, but it doesn’t… it simply breaks documented and expected behavior for aparantly no reason except making the language pure.

    Bugs. All new PHP releases have a bug that breaks existing code. All of them. It gets fixed quickly, but still its no incentive to start running the latest release on a production site.

    And lastly, I hate the way PHP internals works. There seems to be so little unifying direction, and patches or improvements are usually ignored or shot down as not being the ‘php way’. What is the PHP way?
    I don’t know.

  6. spamigator


    Trivial to implement, so everyone brews their own. Dozens of systems, but no single usable system. You can find a Scheme implementing whatever single bit of functionality you want, but nothing with all the functionality you need.

    Syntax a little awkward — blocks and defining variables a bit obtrusive (like pre-C++ C, variable definitions create scope) and verbose. Indentation unclear. Uniformity makes it slower to scan code.

    Code inspection/modification better than in other languages, but could be much better, given the syntax (I should be able to manipulate code as a list).

  7. gnufied


    Somewhat buggy implementation. Crappy garbage collection. At times somewhat weak package/module separation.

    Buggy thread implementation (at least in 1.8.x). No warnings when you override a method defined in parent class or you open a class and override an already defined method. For second case, you can get warnings by using -w flag, but almost nobody uses it.

    I have been always shown the door, whenever I have raised last two issues.

  8. Eric Stein


    As mentioned above, lack of a switch/case statement. What I like best about python (its ability to be both functional and imperative) is left a little inferior to Haskell because of its lack of the beauty that is the haskell type system.

    I just wish Python was selectively dynamic instead of being completely… jiggly.

  9. Stu

    Speed ! It’s just not quick enough to do hard work… hopefully PyPy will fix this.

    + Mobility: I’d really like a standard jython distro for j2me

  10. Delackner

    Objective-C (intwined with Cocoa)

    The flexibility is wonderful, thank you, Scheme. But I often sigh and feel like Icarus with some wax wings looking over at the real birds.

    When I am debugging, I can’t stand when the inspector shows an NSString and in the value field just shows some meaningless rubbish, when it is mind-numbingly obvious it should show the VALUE of the string.

    Why, in an environment that is natively UNICODE, does gdb still barf on Unicode strings unless they are in english? Unicode is not just double-byte english!

    > po [compiledObject knownMethod]
    error: I am too stupid to look up what the declared result type is, please hold my hand
    > po (id)[...]

    Give us simple syntax to use functions as objects.

    Screw C compatibility, wherever it impedes writing new syntax. As long as I can load C libraries, stop worrying about breaking C when the alternative is far better syntax.

    I want a compiler switch to force (except where explicitly disabled for performance-sensitive blocks) int, float, and double to be transparently converted back and forth with NSNumber, and NSNumber to just disappear in the background.

  11. Greg Davies


    Can I please have some curly braces? What is so inherently incompatible about functional languages and curly braces around the functions?

    XML based programming languages like XSLT

    I love how easy it makes everything I do with XML, but the fact that a programmer has to write XML by hand brings shame to our profession.

  12. Henrik


    Type erasure makes me sad.
    Number system like in Java, not possible to write common operations on all numbers without boilerplate. (Haskell’s way of doing this is so nice).
    Error messages are sometimes confusing.
    Type inference lacks the power of Haskell (for a good reason, but still).
    Verbose built-in syntax, like ‘match’ and ‘case’, but not a bid deal.
    Library API is documented poorly. (There’s going to be a community support for this, however).
    No metaprogramming system :(. This means Function traits and Tuples etc are script generated. Also hard to make generic functions that operate over different types of Functions or tuples.
    toString method on all classes with concanetation ‘+’ means there can be nasty bugs. anyType + “string”
    No properly working IDE yet (hopefully coming soon).
    Compiler bugs when dealing with advanced stuff or corner cases, though developers quickly fix important ones.
    No multimethods.
    No standard graphics library.
    No annotation for pure functions, unlike Haskell.
    Tail call optimization on JVM sucks.

    However, I’m convinced that many of these issues are in better shape at the end of this year.[/optimistic]

  13. T


    Not quite dynamic typing. Far too often I end up fixing a bug by wrapping an “int()” or “str()” around a variable. This may be more telling of my programming skills than the language itself, but when throughout the course of my program, ‘foo’ is always a number it drives me nuts when I have to cast it as such just so another method doesn’t take it as something else (what that something else is, I don’t know!)

  14. Danny


    Doesn’t play well with other tools: all those text manipulation tools in Unix; your favourite editor; your favourite source control system — all out of reach.

    Speed: modern JVMs kick the backside of any Smalltalk VM up and down the street in terms of performance, especially with the dogged persistence to use only green threads.

    And the UIs look seriously dated and crappy.

  15. tutufan


    - No good way to check whether “a.b” is valid or not at “compile” time, so you may discover at runtime, even in a program that’s been working fine, unchanged for years, that you forgot to import some library.

    - Programs like pylint, pychecker, etc., that might address the above problem, are usually targetted to a python one version older than the one you’re using, so they don’t help.

    - Similarly, distribution versions of python-mode.el are often behind.

    - I’ve had an open bug with a patch that hasn’t made it into the the trunk in five (?) years or so. No one seems to object to it–it’s just stalled.

    - When Python throws a type error, it’ll tell you that your type is wrong, but it doesn’t print the errant value or even its type, which leaves you to guess, or add print statements.

    All that said, it’s still my current favorite.

  16. Pseudonym

    Wow, you’ve pre-empted pretty much every quibble I have with Haskell.

    There’s one I’ll expand on, though: Some data structures have logically similar interfaces (e.g. mutable arrays and Data.Maps), but one type “lives” in a monad (arrays) and one doesn’t (maps). It’s pretty much impossible to share a typeclass between them, or to easily replace the use of one with the use of the other.

    Now: C++

    Well-written template libraries are a dream to use, but they’re painful to write. Like, really, really painful.

    OK, let me rephrase that. They’re easy to use so long as you don’t write any type errors. Then, you have 1kb long error messages to deal with.

    Lots of things in C++ have four varieties: thing, const thing, volatile thing and const volatile thing. There is no nice way to introduce polymorphism here.

    Meta-object protocols are important in a lot of Serious C++ Applications, but nobody knows how to do them in a consistent and sane way.

    Compile-time-only template instantiation is a necessary evil. But it’s still evil.

  17. David R. MacIver

    Yeah. The difficulty of sharing a type class between certain things is a real pain. Another good example of that (which I meant to mention but forgot) is that Data.Set can’t be a monad because of the Ord constraing on certain functions.

  18. Taylor Venable


    Why is it that runtime error messages produced to the user through the runtime environment have to maintain their internal tuple form? I shouldn’t have to decipher a very long {badmatch, …} tuple (especially when processing XML) to find out I’d written #xmlElement when I meant #xmlText.

    Also, syntax errors are terrible, and usually all you get is something like “syntax error before ‘.’” which makes it difficult for new users to adopt. I guess PHP is the same way (at least PHP4 was) in that it gives a compiler message like “expected TEND”.

  19. Friedrich

    No GC, no bound checking, functional abstraction is “near non existent”.

    Sma(ll,rt)Eiffel, who needs backwards compatability?

    Common Lisp:
    easy of library use, stability of APIs

    Emacs Lisp
    scoping rules, lack of a decent Data Structures, non straigt-forward programming model

    lack of decent Editors and Apps living up to the “quality” of Smalltalk

    Ruby: smalltalk like IDEs ;-), embeddebility

    Scheme: which scheme should it be today ;-)

    Shell: who can learn all the dependencies?

    Io: naming of List

    Self: not available that easy on the diverse Systems

    Haskell: sequential programming, error messages, debugging and tracing, a decent IDE

    Ocaml: Syntax, when to use ([ ]};
    how many ;?

    Visual Basic for Application: how can keep one track of versions and how can one build proper Datastructures with ?

  20. dkfn


    Generics don’t make sense.
    Pervasive use of nulls and the resulting NPEs.
    No function pointers.
    No closures.
    No predefined map or list syntax e.g. {“x” => “y”, “z” => “x”} for a map.
    The static keyword.
    No mixins.
    No open classes / implicits.
    Many competing component systems (OSGI and JSR 277 and then one for every JEE spec, rar, war, ear, etc.).
    No language support for properties.
    Memory usage is pretty bad.
    Startup time is slow.
    No type inference.

  21. Alberto

    By far the best language (with Clean), and one of the greatests human achievements but:

    Haskell programmers are in an ethernal dialog with the (very inteligent) compiler, but when such intelligent being talks, sometimes the messages are obscure in his metalanguage of metatypes and meta-abstractions.

    Some runtime errors untraceable

    do not incorporate logic inferences, like Curry. So it is the half of a declarative language

    HS Plugins unsupported in windows!!!

    Monads: use them, but don´t create them, or else you will end up doing nothing practical, except playing with more and more abstractions until you abandon the sensible world.

    lack of Haskell extensions

  22. Victor


    Absolutely the best language I’ve seen in my life.

    Most annoying

    MPTC: Infernal compiler errors and type signatures. If not this i’ll be mostly happy with them…

    Qualification of infix operators. At first it was truly shocking…

    Different string/list-types: normal [a]/String vs ByteString.Lazy, ByteString.Strict and so on…

    Monadic with pure. I really want something like liftMAll wich will convert pure function to monadic variant.

  23. Daniel Fischer

    Haskell: The best by far, but – see above – qualified infix operators aren’t pretty, the Numerical typeclasses are poorly designed.

    C: Arrays and pointers, I really hate how they did that. A pointer to thing is a different type than thing, so
    thing* p1, p2, p3;
    _should_ declare three pointers to thing, not three variables of type thing, one of which even has an illegal name. Similarly, the type is ‘array of int’, so int[] a; not int a[].

  24. daryoush mehrtash

    can you please elaborate on this:

    Which brings me to another point – type classes are not first class. The Scala encoding of type classes is clunky in many ways, but a very nice feature is that the things you’re using as type classes are real first class members of the language, and you can bring to bear all the usual tools you have for manipulating stuff.

    Isn’t the “data” declaration the same as types in scala?

  25. david Post author

    No, Scala type declarations are kinda different to what you can define with data declarations. But that’s sortof irrelevant.

    The problem here isn’t types, but type *classes*. Monads are types, but Monad is not. ditto Num, etc. You can’t manipulate instance declarations as a first class member of the language.

  26. Mark Wotton


    ditto on moving stuff between pure and monadic formulations, and it just seems wrong to write everything in the identity monad just in case.

    Ben Lippmeier’s Disciple is an interesting dialect of Haskell that addresses this – it has an effect system that allows you to use mutating references safely without using a monadic syntax. Also fixes up the pretty awful record syntax Haskell has.

  27. Pete

    Coming late to the debate, but I had to add this:

    Victor, if you want liftMAll, have a look at the Applicative interface. While there is no liftMAll, () and () are probably what you’re looking for. (Actually you can do this without Applicative just using return and `ap`, but the Applicative interface looks nicer.)

    Have to echo all the other criticisms of Haskell though. Speaking of Applicative, it ought to be a superclass of Monad – you can always define pure = return and () = ap – but it isn’t. Similarly you can always define fmap = liftM but Functor isn’t a superclass of Monad (“Can’t infer “Functor m” from “Monad m” is always annoying).

  28. Draeden

    Coming even later to the debate, but this will probably go on for years.

    PLT Scheme SUCKS ASS:

    Arguably one of the best programming languages in existence. It’s far more expressive than Python, it has a passable macro system, LOADS of libraries, and a good C function interface, and a glorious declarative GUI library, which must have made the DrScheme IDE (written entirely in PLT Scheme) a piece of cake to write.
    There’s a pattern-matching library, but it isn’t as good as ML’s native pattern-matching. This pattern-matching library is really useful in conjunction with HTMLPrag, a library that converts HTML into S-expressions, and even handles human-written erroneous HTML in a reasonable way.

    However, it’s REALLY SLOW. I should have seen it coming when I saw how slow the IDE was. I wrote a card game in PLT Scheme using the card game library that comes with it. I had to cut out the opening animation (which simply shows the cards being dealt) because it ran too slow, even though it was just a simple loop.

    The last full-blown PLT Scheme project I attempted died on the vine when I discovered I needed 10x the CPU power that I had, after 75% of the project was done– and this was after I rewrote in C a simple string-parsing routine that in PLT Scheme was taking 200 ms per call to execute (adding up to several minutes of execution time– the same routine took only 4 ms in C). PLT Scheme is so slow, that it is unwise to write a program in it that goes more than 3 call-stack levels away from something written in C.

    PLT Scheme also has a really irritating transformer-environment/normal-environment divide, making it so that code you write to implement macros can’t use the rest of the functions in your program unless you do a few gymnastics. I found this so irritating that I tried to modify the interpreter so it wouldn’t enforce this rule. The result wouldn’t run, probably because the byte-compiled system libraries depended on the rule in some crucial way.

    The developers are also willing to force everybody to rewrite their programs, by making sweeping changes to the language every few years. The latest version is utterly incompatible with the HTMLPrag library I mentioned above, because of a decision the designers decided would be better “in most cases”. These changes tend to make the language more restrictive. PLT Scheme becomes more like Java with every release.

    You can’t get the type of a value as a symbol the way you can in Common Lisp. That sucks.

    Plus, PLT Scheme has a gigantic runtime environment, which makes it unsuitable for writing programs that need to occupy several Unix processes at the same time (for example, a CGI script invoked by Apache). Since it’s all in bytecode (which is supposedly faster), you can’t take advantage of the OS’s ability to feed one copy of the libraries to all the processes that are using them. This means you can only use it for serious Web development if you have your own dedicated server, where you can run PLT Scheme’s built-in Web server instead of Apache.

    The default profiler provides useless information, because it can’t isolate the time taken by functions from the time taken by functons called by those functions. I took some time to improve the profiler (in hopes of being able to get my program to run at an acceptable speed), but the result contains a lot of C code, for performance reasons.

    Common Lisp (SBCL) SUCKS:

    In many ways, Common Lisp is better than PLT Scheme. The SBCL compiler produces refreshingly fast code. In fact, I ported a matrix-multiplication function that I originally wrote in D, and it ran faster under SBCL (because SBCL supports true 2D arrays while D only supports arrays of pointers to arrays, costing several extra memory allocations)! Common Lisp is based on a solid standard, so it won’t change in drastic and unexpected ways like PLT Scheme. SBCL’s runtime is bigger than the amount of RAM I have installed, but because it’s all native code, my OS can load only the parts of the executable that are actually needed. For those who think strong type checking and pattern-matching are all the rage, Common Lisp can provide both of them. Unlike the case of PLT Scheme, the CL-UNIFICATION library kicks ML’s ass, plays basketball with it, hands it to ML’s mom, and then butt-fucks ML and its mom at the same time.

    CL’s standard GUI library, CLIM, sucks Swing’s ass. Unlike PLT’s declarative dream library, CLIM is an object-oriented nightmare, and because so much of CLIM is done with unnecessary macros, the structure of your GUI is set in stone at compile time (much like a C++ program using MFC, only worse). As a result, most GUI CL programs seem to be written with TCL/Tk, which makes the underlying CL program feel like it was written in PLT Scheme.

    Lest I forget, there’s a proprietary Common Lisp environment out there called LispWorks that costs $7,000! I can’t imagine what it could possibly do that SBCL doesn’t that would make it worth that figure, however.

  29. Darth Flobbygog


    The Brain Drain. Haskell Hogs a lot of brain resources. Reading Haskell requires more brains than most other languages I use… I find this is because of:

    The language has a fancy syntax, is full of punctuation that you need to memorise and doesn’t lend itself to glancing at it and understanding where everything’s at. It also encourages an attitude of “smaller is better”. It isn’t. For Haskell-fu masters, this may seem a feeble complaint, but I live by the motto “It is foolish to use your brain when your brain is not required”. Fools.

    This is exacerbated by:
    Haskell programmers think that hacky is okay: the “Oh no that identifier has vowels, and resembles a real word! I’ll need to change it in case it’s actually meaningful!” attitude. Or the: “this lambda expression combined with a map on a list comprehension is obvious in what it does – I don’t need to break it down into more verbose components, hell it doesn’t even need a comment! people will be able to read my mind by looking at the type signature!” attitude… the list goes on. These sorts of things mean that you have to think next time you try and read a section of code.

    Haskellians = very clever showoff elitist hacker geeks that don’t have girlfriends because they look like their code… scary, messy, no style and covered in punctuation and acne (unless they’re lucky enough to find a girl that thinks lambda calculus or category theory is a turn-on)

    Please Haskellians, write things nice and clearly, break things down into bite-sized pieces and don’t try and show off your 1337 lambda calculus skillz at the expense of making things harder to understand than they need to be… then you may win some converts to this awesomely advanced amazing language.


    no real concept of scope, no real concept of dynamic typing, no real concept of neatness in its class definitions, no real concept of anything. Helluva useful language, but it’s all over the place and feels hacky to use. Significant indentation is great for enforcing a standard style, but it’s easy to lose track of the end of things at a glance.


    who thought that making a whole lot of libraries with loads of functionality and then saying… oh to make this work you have to completely delete the usual standard library and replace it with this stuff… which is rather buggy anyway??? causing a war of standard libraries… causing problems for an otherwise really nice, fast and super-useful language… Pull the stuff that matters out of Tango and use it as a library, or go screw up someone else’s language that isn’t as awesome as D.

    Can we please have some smart people join the D community? All I see are noobish Windows game hackers who have no eye for good programming practice – they need some role models.

    whoever the LDC / LDMD people are, you keep going strong, i’m relying on you! (and make anonymous delegates work!) GDC is as good as dead.
    (and DMD only compiles to i386 and doesn’t keep up with new platforms – awesome idea for a systems language no?) – yes, there 3 compilers to choose from.

    Some of the template meta-programming stuff (whilst it puts C++ to shame) is a bit hacky too, compile-time evaluation of strings instead of proper first-class functions to implement higher-order functions… you could only get away with that in D.


    why isn’t this dead yet? and
    as for java programmers… especially those that have anything to do with the word “Enterprise”… omg needs moar design patterns!!! … yeah, that’ll fix it, you keep trying to shove logic into data structures until that tower topples over and you have to hire a team just to hold it up.

    Java’s also awesome for making a hello world program that consumes all your system resources.


    i hate microsoft. i hate them for making something like the CLR which is actually half-decent. i hate that they can get some respect when they’re obviously so evil and all… I hate that they’re actually getting smart people to put thought into things instead of relying on monopolistic bullying… they should be more evil and do more wrong things so I can hate them more.


    great idea, crappy syntax.


    hey, it might have been good if it wasn’t for the C bit. C stands for crap. Anything that’s backwards compatible with crap is going to be dragging crap around with it… and a memory allocation model with multiple personality disorder

    that’ll do.

  30. Harold


    Everything that’s been mentioned so far, plus the preprocessor beyond macro definition.

    “A moment of convenience, a lifetime of regret” is a good way to describe how any seriously portable code base accumulates a twisty maze of #ifdefs that are a nightmare to untangle by just looking at the code.

    Perhaps the single “best” C/C++ feature dropped in Java.

    OK, a few more for C++:

    Requires too much of self discipline to avoid getting tripped up by a lot of subtle things like reference parameters and the frequent need to explicitly define copy etc. constructors.

    The language is so big and messy that *everyone* uses a subset, making code sharing between projects problematic.

    Bottom line: C++ is the worst possible language in its niche, except for all others ^_^.

  31. fogus

    Clojure error messages still leave a lot to be desired. After hacking in it for the past year and a half I’ve learned to have a clue what they (sometimes) mean. However, I think that they are the largest barrier for new users.

  32. Pingback: Soi Silicon » The One Computer Language Without Complaint

  33. T

    Unlike many of the comments here, I think a majority of C’s problems come not from the language itself, but how it’s used. C was never intended to be used to write full-fledged GUI applications and other such things, because of this, it’s no surprise that its offerings are very inadequate in this area.

    C’s biggest flaw to me is a combination of gcc and poor error handling. gcc enables tons of compiler-specific extensions by default, which novice programmers who learn by example don’t realize aren’t standard C. This leads to more “GNU C,” and less portable, well-written, standard C.

    Error handling in C is virtually nonexistent–using a combination of enums, perror, writing to stderr and subjective (usually poor) judgment as to whether or not an assert() or exit() should be used under certain error conditions, leading to sporadic and annoying behavior in libraries when errors do occur.

    I agree with basically all that has previously been said on D, but I’d like to add a few more things.

    In addition to the schism between Phobos and Tangos (D’s two stdlibs), there’s also two in-development versions of D (D1 and D2), which are not compatible with one another. The result is that some individuals try to write code for both stdlibs, and/or both language versions and produce code that lacks features (no file reading/writing, socket support, etc), is convoluted and littered with version statements (conditional compilation), or both.

    Getting code to compile on all three available D compilers (dmd, gdc and ldc) is like pulling teeth. There also exists no decent 64 bit code emitter for any of these compilers, last I checked.

    After struggling with all the problems of D, I finally abandoned the language entirely.

    The community of Python is one of its biggest triumphs and flaws, as with Haskell (I’ll get to that later). “Pythonistas” are completely and utterly riding on van Rossum’s nuts and despise anything “un-Pythonic,” and they tolerate virtually no criticism of the decisions within the language, no matter how stupid those decisions are. They’re perfectly fine telling you what you do and don’t need in a language, and any disagreement is sheer ignorance on your part.

    Python is ugly and feels hacky. _this, __this, __this__, xrange, object, explicitly passing self, and the built-in ‘types’ (int(), str(), list(), dict(), etc) as well as len() are all examples of poor design in my opinion.

    Python doesn’t support access modifiers (public, private, protected, etc) and the usual recommendation for ‘private’ is to prefix the variable with single or double underscores (e.g., _foo, __foo), the former of which offers no protection against accessing (you can still do the_object._foo) and the latter of which performs name-mangling, still offering no protection against access (__foo in the class Foo becomes _Foo__foo, and can be accessed and mutated via the_object._Foo__foo). While this may not seem important, I primarily write cryptographic libraries and would much prefer if I could protect some code against accidental modification by a user during runtime (there are ome hacky ways to do this, but it’s still hacky).

    Super in Python is just sad (and was broken in slightly less recent versions). You have to explicitly call the superclass’ constructor, which involves an ugly __init__ tacked on.

    The usual fix for a lack of switch/case is a dict which maps to lambdas or functions you pre-defined. In my opinion, another example of Python’s hackiness.

    I really think Python should nest its standard library within ‘std’, ‘stdlib’, ‘python’ or similar, as I don’t know how many newcomers I’ve helped who had namespace clashing issues (had a in the same folder which would be imported in place of the standard random module).

    Speaking of which, Python’s stdlib is poorly organized and named (not as poorly as PHP, but still). In ‘urllib’ and ‘hashlib’ the ‘lib’ is redundant, and shutil has absolutely nothing to do with shells. The difference between ‘sys’ and ‘os’ is vague, and so on.

    The lack of the ability to subtype in SML is what deters my significant use of it. That, in combination with reals not being an equivalence type (you can’t use foo = bar with reals, you have to use Real.==(foo, bar), which is very annoying). Ints have their own division operator (foo div bar), but that can be overcome with a simple fun (x:int)/(y:int) = x div y, so it’s less of an issue than with the reals (which you can’t implement = for).

    The comment above that Haskell is “one of the greatest human inventions” reflects the attitude of most Haskell programmers I’ve met. The usual issue I have with Haskell programmers is that they’re all riding the fanboy wagon and none of them seem to know why. Most of them have absolutely no idea what a monad is (no, it’s not “something that describes a computation” and copy/pasting from the first paragraph of Wikipedia just proves my point), or the consequences of a functional language being pure. They throw around buzzwords like “referential transparency,” and “laziness” without ever having studied the implications of either. They all remind me of the kid who wants to look smart, act smart, and talk smart, but never takes the time to actually get smart.

    As far as the language itself goes, the convoluted implementation of almost anything involving state (IO, for example) is what pushes me away from Haskell (at least the implementors of SML realized how futile functional programming is for inherently stateful operations).

    Also, the ability to create a ‘monad’ in Haskell which doesn’t adhere to the monadic axioms is just mind-boggling to me. Why would you rely on the programmer to adhere to these axioms when they more than likely don’t even understand what a monad actually is?

    May require a followup.

  34. odrzut

    Clojure – error messages are horrible,
    using/requiring/importing libraries is more convulted than it could be,
    to run clojure program you have to specify classpath with all classes it uses

  35. brazzy


    Most of the problems boil down to one thing, which is also responsible for a good part of Java’s success: Sun’s obsession with downwards compatibility.

    - It makes adding language features agonizingly slow and often leads to ugly compromises (such as generics based on type erasure)
    - It leaves the API library cluttered with warts and remnants of design errors, many of them left from the days of Java 1.0

  36. bgsu_drew

    * Too low level – try doing common tasks such as converting a file to a string or validating XML against a schema. Java is definitely not meant for scripting.
    * Tools are maddeningly slow, like try redeploying to an IBM Websphere server.
    * Constantly changing enterprise standards that make it feel like you are trying to hit a moving target… and none of which ever seem to get the API quite right. Is EJB3 great? I dunno, cause my company is stuck using EJB2 on WAS6.1 on J2EE v1.4.
    * Java code is not elegant or fun. Yeah, it’s subjective, but there’s no closures (Predicates don’t count) and no literal collection initialization.
    * Many frameworks required to do anything useful and high barrier to entry. Front End (Struts) + Data Persistence (Hibernate) + Wire it all together (Spring) + Build System (Maven) + App Server (Glassfish). This is exactly why Rails and Grails so attractive to web developers.

  37. Jason

    Here are some of my favorites.

    Scheme: it lets you do horrible stuff, just like C++ and Perl. It does not provide monads.

    And here’s what I don’t like about Haskell. It forces you to declare types. It’s not as bad as declaring classes in OOP, but it can still be a pain. I like nearly typeless Scheme, when it comes to that.

    I know: without types, you can do horrible things.

    How about lazy Scheme with monads? I know, that sucks, too.

  38. Jason

    Another reason Haskell sucks: its syntax is difficult to parse. The indent convention makes it so. Difficult parsing is one thing that turned me off from C++. If it’s monstrously complicated, there is no guarantee the compiler is correct. And a correct program created with a buggy tool is a buggy product.

    One thing that sucks about most languages: either the syntax is complicated, or the execution model is. Usually, both in fact are. The ideal programming language should be simple in design itself yet flexible. That way, it is easy to get the compiler right, so that whatever complicated product is created will run as correctly as it is coded. This is one thing Scheme has going for it: simple syntax, simple execution model.

    If the data model (or the object model, if you will) is grotesque, that’s another factor. I’m not sure I’ll ever understand the object model of Haskell. It seems Haskell data types are like immutable objects. So we have essentially immutable object-oriented programming. Plug it into the IO monad replete with IORefs, and you get fully mutable objects! You can even create abstract data types by using multiple constructors. You can use type-classes in the way you would interfaces in C#. Like the latter, it defines a contract. With each feature, the complications mount. I like to work with simple object models, mutable or not. Another thing going for Scheme: you can use closures in lieu of objects, and you get the benefits of OOP without complications.

    Since all languages suck, I think I’ll eventually create my own. It will be without data types, like Scheme. It will use a simple syntax, like Haskell without indents. A B will mean apply function A to argument B. A B C will mean (A B) C, just like in Haskell. All datas will be assumed to be one-argument functions unless proved otherwise at run-time. Internally, there shall be just four types: Integer, function, pair, and (). Lists shall be pairs, just as in Scheme. Array shall be an optional fifth type, but only if the user includes the Array library. Externally, there is only one type, data. When evaluating A B, the runtime determines if A is a function; if not, it’s an error. Then A is applied to B, whatever it might be. All functions are automatically polymorphic on all data. Lambda-functions and currying shall be the idiom, as in Haskell. If the IO library is included, that gives a sixth and seventh type: the action and the reference. The IO library will print lists of Integer as strings. Finally, all operators are prefix. No x + y, etc. If the programmer doesn’t like it, too bad.

    The compiler will use no optimization. Just straight translation into native code. This actually makes back ends easy to write. The real purpose of compilation is to make the language able to compile itself without adding overhead at each iteration. This is good for bootstrapping if one wishes to improve the language incrementally.

    There is just one problem with my language: it too will suck.

  39. Jason

    Another reason Haskell sucks: compilation takes too long. Just like in C++. These compilers try to do too much. They have to do too much backtracking to accurately parse. Then they have to optimize. Simple syntax plus no optimization means: compilation should be fast.

    Have you noticed that a C++ compiler typically takes 5-10 seconds to compile one-liners, whereas assembly is instant? Assemblers do not do optimization, because that is assumed to be entirely the programmers responsibility.

  40. shiny666

    well i have beef with everything i’ve tried, but here goes null. get it?
    before i get into specifics note that the worst thing i’ve seen in most languages is the documentation, and while at times sufficient, often the examples are more distracting than clarifying. also i have found quite a few resources that are mere redundancies, which while useful in a purely archival sense, is frustrating when searching for alternate examples and descriptives.

    - scope of variables through recursion and related syntax. i.e. i’m such a failure at racket that i can’t even parse a list properly because i can’t understand why syntax errors arise from letrec that don’t from let.
    - the use of parentheses is blinding me, really it is.

    – the use of double semicolons as a form of closure
    – semicolon-delimited lists

    - space-delimited (yes it’s a nice learning feature, but it gets old quickly, imo)
    – duck typing. inferred typing in ocaml was one of the only things i liked about it. this is far from that.

    – everything i can remember about java. it reminds me of broccoli (the vegetable), except i’d rather choke to death on broccoli than read or write java.

    – standard scope of variables. i have to decide whether to unset or reset variables instead of worrying about how to pass them as arguments.
    – conditional syntax in general, esp. case
    — using the reverse of the word for a statement close (i.e. case … esac p.s. anyone remember casting the spell epor?)

    1. Jason

      I agree about documentation. That is a beef I have with almost any language out there. The language is usually bigger than I want. Certainly, no one completely understands it, unless it is Scheme as taught by Sussman, who by the way did not teach me let-wreck.

    1. Jason

      Functional programming is supposed to be: formal, reliable, mathematical, and bug-free. Functional programming filled with built-in high-level constructs that no one really understands is not. The core should be tiny, with all over-your-head abstractions derived, not built-in.

  41. Jason

    An example of what I mean:

    Anyone who has done functional programming has probably encountered the function map. Something like map sq [1,2,3,4,5] computes to [1,4,9,16,25]. map is easy to write, but no one writes it oneself. Rather, map is a built-in function. My radical opinion is that map should never be built-in. It should be available in a library, but the library should exist as actual source code that would compile or run in that language. The library should not be mere object code that was compiled by another language.

    map is easy to understand. It can be explained mathematically. One can easily get a handle on exactly what map does and use it with confidence. There are many good tutorials that include map in their examples of the power of functional programming. It should be the same with every level of abstraction from the simplest to the most complex. The documentation should always be available as open-source information. If the abstraction has a basis in a mathematical theory, that theory should be included in the documentation, so that anyone using the construct can understand and use it with confidence.

    For example, you have probably seen list abstraction, which is similar to set abstraction. As a mathematician, I like set abstraction. As a programmer, I avoid list abstraction, unless I know how it is implemented in the language core.

  42. Jason

    The Evil Mangler

    When it comes to Haskell, the elephant in the room is the Evil Mangler. It is no misnomer. To mangle code in order to accomplish a workaround or an optimization hack is no small evil. It goes against the modularity and reuse principle which is the core of Haskell philosophy. It is the wrong way to write a compiler, period. Just like C++ uses name-mangling, Haskell uses code-mangling. It is all evil. Haskell should have been bootstrapped from assembly on some high-speed computer and then used to port itself. It should never have been developed by means of kludgy hacks. It should have been a pure boot job, not a combination of Perl, C, and itself. So you believe in pure functional programming? I do too. And I also believe in pure bootstrapping.

  43. Westley

    Lack of consistent error handling. Personally I use return codes myself, but not everyone seems to like that style.

    The feature creep of the language as well as the unnecessary changes that occur between versions. Also operator overloading is strange, but Python’s polymorphism is awesome so that makes up for it.

  44. Mike


    The documentation of the core language and 95% of the gems suck. In Ruby acceptable docs include: source code, no API listing, and books. JRuby has this disease as well.

    Most gems are 80% solutions and it is easier to roll your own then to try to and figure out these mostly undocumented gems.

    lambda/Proc needs to be cleaned up

    1.9.x has a GIL

    yes, only two complaints that has to do with the language

    too verbose
    not at all expressive
    Too much boiler plate that adds nothing to the readability/maintainability/testability of the code and only exists to placate the compiler. I have seen class files that are 200-300 lines long and only 25% of it actually had anything to do with the functionality of said class.
    No reasonable metaprogramming and reflection facilities.
    Difficult to test private methods properly
    Near impossible to test a child class independently of its parent, and the parents parent, and …
    Factory Factory Factories
    No mixins -either have to blow your only inheritance spot, or use interfaces which cause either
    1. repetitive code- lots and lots of it via implements Stupidable
    2. Lots of stupid delegate methods cluttering up your class <-composition is preferred(aka lots of boilerplate besides all the other bloat that the language enforces).
    No first class functions, kingdom of nouns indeed. What happened to the central OOP concept of message passing? Did anyone developing Java know what OOP really is?
    No anonymous functions
    The only thing resembling the property closures* are the various inner class constructs.
    Java programmers love to abuse XML.

    *pet peeve alert – closures are a property of a construct, anonymous functions/lambdas/blocks are constructs. I wish people would stop using closure when they mean lambda. You could implement anonymous functions in a language that do not close over variables in scope. ie doesn't support closures

    enforced whitespace is not only annoying** it removes a lot of power ie no multiline lambdas are possible because of the whitespace crap.

    No reasonable break/continue

    No switch statement

    When you bring deficiencies up the community says "guido told us we don't need them, but if you really do want that pointless functionality try this terrible hack that makes Java seem reasonable"

    Horrible bolted on OOP.

    __len__ just so you can call len(obj)???? WTF

    Just might have a more annoying community than Haskell's, which is funny given that as anal-retentive as Python programmers can be, the language is not nearly as anal-retentive as Haskell. Don't worry PHP's community of amateurs is much much worse then Python or Haskell

    **Everyone uses whitespace to format their code, so enforcing it at the cost of a weaker language is pure idiocy. It doesn't buy you anything.


    It is easier to list what I like:

    1. Nothing


    Desperately needs an update. C used to be a reasonable lowish level abstraction of the underlying hardware. It no longer is.

  45. Sebastian


    I used to do some template programming in templates and liked it, but I’ve changed my mind and my advice is now: Just screw them. Here’s an example of the new C++11 style:

    auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}

    This syntax is so fundamentally broken and hacked in to a language. Here, that they needed two return types. The first one is before the function name and the second one is between the parameter definitions and the body. Just compare this to Haskell.


    Type checks? We don’t need them, just let the code crash on runtime.


    Did I say boilerplate? Sorry, I meant Java, but I think this is obvious.

  46. Pingback: Best of | David R. MacIver

  47. hari

    Still a newbie to Haskell, but I really like Haskell and functional style, but my own pet peeves are:
    - Lack of proper documentation (and I don’t count generated docs from source code as proper documentation) for libraries. Every library should have a basic “how to use” section and this is a common problem in many other languages.
    - Tutorials are too basic and then take off to advanced concepts leaving the reader bewildered at times.
    - Half baked bindings and incomplete libraries. Already ran into the issue with HSCurses and a few others.
    - Too wrapped in theory. I love the potential, but due to the aforementioned issues, I find it hard to use Haskell practically. Most of the chat on Haskell seems to center around the beauty of its abstractions and more theory.

    Am a big fan of Python, but again my peeves:
    - Slow.
    - Duck typing.
    - No possibility for a native compiled executable due to the nature of the language itself.

    Significant whitespace is not so much an issue for me, though.


Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>