Talk:YourLanguageSucks

From Theory.org Wiki
Jump to: navigation, search

Lua Sucks

  • 1. Variables are not global by default in a sense like other languages. They are global to their environment, _G._G just happens to be the default. It is a very powerful feature for use with metamethods and setenv. Do you realize how much of a pain it would be if you did this:
    • local this = { is = { a = { deep = { tbl = true } } }

And you had to explicitly state each time it's a 'global' just so you can access this.is.a.deep.tbl from some other scope? It only makes sense that it's global to env by default.

    • local this = { global is = { global a = { global deep = { global tbl = true } } }

This would seem ridiculous.

  • 2. What do you mean you can't store varargs for later or operate on them directly? You can do such things as
    • if (select('#',...) > 0) then local args = {...} end
  • See here: http://emmanueloga.com/2010/12/09/lua-select.html
  • 3."Table indexes start at one" - So what? The point of lua is human readability. Is i-1 so hard if necessary?
  • 4. "which will work till you'll want to copy a table with __index metamethod." -- It's called rawget and rawset; use it they bypass metamethods.
  • 5. "Lack of object model." -- I think the real problem is people try to emulate other languages using lua, by trying to re-create 'classes'. Learn how to use metamethods and environments then you will see what power comes with it's simplicity. Everything IS an object model, environments (_G being default) are essentially tables themselves that obey whatever methamethods you setup. You can create very modular setups or complex component entity systems with ease. Seriously, anyone who claims that Lua isn't OOP is retarded.

Some real reasons why Lua sucks is base lua is slow and a memory hog. LuaJIT 2.0 is fast, even faster then most other runtime languages, like Java, but LuaJIT has a flaw in that it's Garbage Collector can only handle 32-bit memory addresses making it not suitable for x64 without workarounds. Lua is barebones, meaning you have to make or find libraries to do just about everything, which has it's pros and cons.

CSS Sucks

  • Contrary to your argument given for a lack of transparency, CSS actually does support transparency as of CSS3. This is implemented via the opacity attribute. --Crazy Pothead 23:58, 4 October 2007 (PDT)
    • CSS 3 is not an official spec yet and is not supported by all browsers.
      • This is not a problem of CSS A71104
        • If a standard isn't widely supported, then it sucks regardless of whatever good intentions it may have had. The #1 problem web standards have is that browser makers don't give a shit and just do their own damn thing. There's stuff in CSS v1 that isn't handled right across browsers, I've run into it on several occasions (and it usually involves tables). -CppThis
  • CSS isn't a programmable language but a descriptive one hence not being able to programmatically set a color or a length is totally normal. -BinarSkugga

Python sucks

  • "the syntax for conditional-as-expression is awkward in Python (x if cond else y). Compare to C-like languages: (cond ? x : y)" really? I don't see how the latter is clearer - quite the opposite. The python reads as you'd expect it to, and calls back to the normal if: ... else: ... syntax.
  • Removed 'inefficient JSON dumper: leaves spaces along with commas' - takes 'separators' - an argument that allows you to specify the more compact version if you want to make it completely unreadable.
  • Removed There are strings, and then there are Unicode strings. No justification was given. Python's Unicode strings allow for superior Unicode support than Ruby & PHP, and nothing in Python forces you to use Unicode strings -- you can write an entire application that uses only byte strings and do encoding support the Ruby/PHP way.
    • It is not the existence of Unicode strings that is the problem. I would say the bigger problem is that the str strings are used for text at all! Fortunately this is fixed in python 3.0. The sad thing is bytestrings and Unicode strings are not interchangeable. There are very very subtle bugs also, that will kick you hard in the butt, for example b64encode WILL BARF if fed unicode strings AND the 63rd and 64th characters are specified. Just guess which one of these will throw a runtime error: base64.b64decode(u'YQ==', u'+/'), base64.b64decode(u'YQ==', '+/'), base64.b64decode('YQ==', '+/'), base64.b64decode(u'YQ==', u'+/'), base64.b64decode(u'YQ==', u'+/'), base64.b64decode(u'YQ=='), and base64.b64decode('YQ=='). They should all be equivalent, but the first two barf out. As base64 is embedded in text data, the objects might as well be unicode. --Ztane 14:15, 15 July 2011 (PDT)
  • Removed The syntax for singleton tuples, (x,), is confusing, and different from the syntax for singleton lists. Python syntax for tuples uses commas; parenthesis are used to disambiguate when the context requires it (mostly on expressions). For example:
 spam = 1, 2, 3
 spam = 1, + 2, 3 # spam will be 1, 2, 3
 first, second, third = 1, 2, 3
 alone = 1,

--Cesare Di Mauro

  • Removed: -1 ** 2 is -1 ???. The unary - operator has lower precedence than **. So -1**2 actually means -(1**2). (-1)**2 is 1.
    • This had popped back on the page. Unary - has never had precedence over ^... not even in my highschool math classes...
  • Changed: Added a notice for != and <>
  • Removed: there's pow() and **
    • well, why did you? isn't that an idiotic duplication? A71104
  • Removed: you can do list[1] = x, but you can't do dict['abc'] = 123 (you have to use the unintuitive dict.update({'abc':123}) instead...)
>>> d= {}
>>> d["abc"] = 123
>>> d["abc"]
123

perfectly works

...Uh. Well, that's weird. Maybe it wasn't like that in an old version, because I'm sure that didn't work when I tried it ages ago, so I never bothered trying after. But if it worked from the start then I'm just confused. Keiji 09:01, 23 March 2011 (PDT)
  • Removed: "If variables would be need to be declared similar as in JavaScript you would not need this." In JavaScript, you can actually use a variable like:

for(i = 0; i < 10; i++){ and guess what? Now you have the variable i in your global namespace!

  • Removed: "as is typical of major revision updates, there are breaking changes between Python 2.x and 3.x"

There is nothing typical the transition from Python 2.x to 3.x. It was always intended to break backward compatibility when necessary to produce a better language. Therefore, it might be better to think of Python 3.x as a distinct language from 2.x. This is supported by the fact that 2.x has continued to be updated well after 3.x was released, gradually absorbing some features from 3.x in a backward-compatible way.

  • Removed: "what is a bigger indent: more than one white space or one tab? and why shouldn't a programmer be able to use { } to define any arbitrary block?"

This was badly worded at best. The choice to use white space to structure code explicitly was a conscious design decision which the lack of block begin and end characters is consistent with.

  • No mention of threads? How absurdly hard it is to do async IO? GIL? :-) --savv

Python sucks, but some of these reasons suck worse

Since I am a python fanboy, I'll temporarily recuse myself from editing the python section, and instead make my comments here. I assume that language features that have a greater benefit than cost are not reasons for a language to suck.

  • What is bad about having pow() and **? The benefit is straightforward: Having an operator is nice sugar, and the non-operator version allows modular exponentiation (more efficiently than (x**y) % z). Of course it defaults to mod-infinity, which gives it the same semantics as ** in this degenerate case.
  • Why is it suckage that you have to implement __len__ to get len() to work? That's also how you get support for other operators and builtins, like __add__, __lt__, __getslice__, __contains__, __abs__, and so on. Whoever wrote this must hate operator overloading in general, which is fine, but the complaint should be changed to "single-dispatch operator overloading and builtin overloading is possible"; it would accurately paint what is going on. Or maybe you're actually sad that builtins are not all operators? Like maybe you'd like len() to be an operator, and then also abs(), and then also 'in'? This is just incoherent.
  • I think it's a bit unusual to complain that there are breaking changes from 2 to 3. Isn't that what a major version number change means? But then again, yeah, it sucks, even if it's how every language and every piece of software ought to work.
  • Whoever wrote "no tail recursion" doesn't deserve to complain about it, because the thing one might want is tail call _elimination_ (a.k.a. tail call optimization). Tail recursion, that is recursion via a tail call, is a property of functions as-they-are-written, not a property of languages.

--Jholman 23:41, 12 July 2011 (PDT)

I'll add something to this:

  • "no assignment in while condition": This is a good design decision. It is a very common bug to accidentally only type one = when you've meant to type ==. Convenience isn't always a good thing. (I too, was confused by this one. I've wished that it was legal syntax much less than I wished for a notification in C(whatever) User:waynew:waynew)
  • "No labeled break or continue": The consent is that such features tend to produce bad/complicated code much like goto does. And goto is listed as bad thing for other languages, so this is rather inconsistent.

--Panzi 16:50, 11 April 2012 (PDT)

I'm letting it stay though, because it also means you have to initialize variables before the loop, and it's one of the reasons for the annoying "while True:...if <condition>: break" pattern. --Regebro 05:14, 17 February 2013 (PST)
  • The complain about `(-1) ** (0.5)` giving an error instead of a complex number is ridiculous: when one performs arithmetic in the integer/real/complex realm, it expects to obtain results in the integer/real/complex realm as well. `4 / 3` gives `1`, but `4 / 3.0` gives `1.3333333`. That is, if you write `(-1+0j) ** (0.5)` you get the expected complex result. The same operation in the real realm is not valid, hence the resulting error.

--Jerome 11:44, 19 December 2012 (PDT)

  • "This means in order to change global variables or variables in the closure you need to declare those using global and nonlocal in the function in which you change them." - Uh, and since when is it a BAD thing that you have to explicitly declare that you want a variable to be global? --Regebro (talk) 00:47, 26 June 2013 (PDT)

A few more to add

  • Removed: "Many libraries return tuples from function calls and you have to dig through documentation to figure out what the fields of the tuples mean; if they returned dicts instead like in JavaScript, the field names would often be self-explanatory without documentation"

This comparison to JavaScript is inconsistent since JavaScript doesn't have arrays, lists or tuples, which is cited as a reason JS sucks.

No examples are given which demonstrate cases of confusing return value order.

Also, just as a simple example (again, since none are given):

x, y = something.getPos()

is cleaner than

pos = something.getPos()
x = pos.x
y = pos.y

Besides, any language that doesn't allow multiple return values is declared to "suck" for not supporting it. The fact that Python functions can return multiple variables is considered a reason it "sucks" seems odd at best.

Finally, since this is a complaint about "many libraries" (which ones?) and not the language itself, it can't really be a reason Python sucks.

  • Removed: "The syntax for tuples, x, is very subtle. If you add a comma to an expression, it turns into a tuple. This can lead to errors that are hard to see"

The examples given are no worse than missing a semicolon at the end of a line in C/C++/Java, etc. If anything, the only real problem here is that you get a tuple when you would expect an error, so if anything, this is all just a subset of the fact that Python is a late-binding dynamic type system. In other words, it would be like complaining that if you do x = "4", x is a string instead of an int like you might have meant.

  • Removed: "default values for optional, key-word arguments are evaluated at parse-time, not call-time"

This is simply incorrect. The default values are evaluated at declaration-time, not parse-time; function declaration happens at run-time and follows natural flow control. They are a part of the declaration, not constants. They work as expected within closures, for example:

def f(a):
    def g(b=a):
        return b
    return g

In this case f(4)() returns 4, and f(5)() returns 5. The value of a is evaluated as the default value for b at the time that g is defined, in this case, whenever f is called.

Besides, what would be the alternative behavior? Evaluating code in the definition of a function when the function is called?? Why would you want such dangerous and unexpected behavior? Clearly the only thing that should be evaluated when you call a function is the function body, right?

  • Removed: "There is no "do ... until <condition>" type of statement, forcing the use of patterns like "while not <condition>:""

Firstly, the fact that whoever wrote this equivocates between "do ... until <condition>" and "while not <condition>" demonstrates that they don't even understand the purpose of do-until because they aren't equivalent. A do-until always evaluates its body at least once, while a while-not construct doesn't necessarily. At a minimum, this complaint should be edited. But:

The existence of "unless" is cited as a reason Perl sucks because it's redundant and you could just do "if (!condition)", so why is the *lack* of the redundant do/until bad when you can easily just do a loop-and-a-half construct? Also, many complain about the readability problems of do-until structures; namely that putting the condition at the end of a (potentially long) block of code reduces readability. So, arguably, do-until is actually worse than the "unless" constructed cited as a reason Perl sucks.

  • Removed: "Co-existence of python2.x and python3.x on a linux system is very painful"

This is, at best, a reason why Linux (distros) suck, not a reason Python sucks. You have the same problem with multiple Java versions, multiple shells (what is /bin/sh, anyway? Bash? Dash? Ksh in Bourne compatible mode?) multiple PHP versions, typing "sl" instead of "ls", etc, etc. Besides, most Linux distros that include Python 3 have explicit python3 executables, so if you're writing a Python 3 script, you should always use #!/usr/bin/env python3 anyway. Problem solved.

  • Removed: "The main function construct is awful and probably the worst I have ever seen if __name__ == "__main__":"

This demonstrates a fundamental lack of understanding of how Python works. This isn't a "main function", it's merely a convention for a Python script to differentiate between when it's being run as a script and when it's being imported as a module. If you're just writing a script, you can just write it like a script. Python scripts are evaluated and executed line by line like any other scripting language. You don't have to use this convention. In fact, many would argue that if you're using this convention, you're approaching it all wrong anyway, because your Python file should either be strictly a module, and thus only contains class and function definitions at the top level, or should contain program logic at the top level if it's a script meant to be run directly. See __name__ == __main__ considered harmful

-- Memotype (talk) 14:18, 9 May 2017 (PDT)

PHP

If no-one is opposed (or I can get support for this idea) I would like to clean the list of reasons why PHP sucks up by putting things in logical sections rather than one muddled list. -- Potherca


  • code must be inserted between <?php and ?> tags
    • how can the interpreter know where the html starts and where the php starts without start and end tags? --Alias
    • It doesn't need the ?> if the entire file is PHP (in fact, this is preferable). Matt 15:54, 18 June 2009 (UTC)
  • there's one is_type for each type: is_int, is_float, is_string, etc. to check for a proper type
  • ++ and -- cannot be applied to booleans
    • why would you do that? --Alias
      • To change it to its opposite. $foo = false; $foo++; $foo #=> true Matt 15:47, 18 June 2009 (UTC)
        • There is a boolean unary NOT operator for that; nobody uses ++ and -- on booleans, moreover ++ would only work on false and -- would only work on true (right?). --A71104
          • Why not just !true or !false like every other human being would do? --Karim (talk)
            • Technically being in base 1 adding 1 to either true or false should return the other, so while its incredibly lazy and could easily confuse a passing glance, $state++; should change $state's value of false/true to true/false respectively.
  • Constants do not use $ prefix, like variables
    • I might be missing a point here, but why is this a bad thing? I always though having that distinction was helpful? -- Potherca
    • You aren't missing a point, it isn't a bad thing, a constant and a variable are 2 different things and at least the language makes the effort to discern between them.
  • there are two ways to begin end-of-line comments: // and #
    • Why is this considered to be "sucky"? I though having more choice would make people happier... -- Potherca
  • (instances of) built-in classes can be compared, but not user-defined ones
    • This seems very much like a false claim to me... -- Potherca
    • Yeah that's rubbish. Learn what the comparison operators are and the differences between them.
  • there's no integer division, just floating point one, even if both operands are integers; you must truncate the result to have back an integer
    • Seems to work fine for me. In fact, the opposite appears to be true: echo(gettype(5/1)); echo(gettype(5.0/1.0)); The first returns type integer, the second returns type double. If echoing the result of the calculation instead of the type, both simply return "5". -- Squingynaut
    • No, and what the user complains about can stay in the deep dark pit where it belongs. There are 2 parts to this, one is dynamically typed variables, so 5/1 will return 5, and 5/10 will return 0.5, keeping the world so nice and fluffy and safe. The second part is what special breed of evil wants 5/11 to return 0? if you must require such filth, use intval(5/10) or floor or ceil or some other function to make the code less dangerous to your users.

Object-oriented programming sucks? Perhaps not.

  1. "Object-oriented programming is an exceptionally bad idea which could only have originated in California." --Edsger Dijkstra.
    • Well he was dumb. OOP dramatically improves the scalability of programs.
      • I agree; remember the "arrogance in computer science is measured in nano-Dijkstra's" thing? A71104
      • Suggesting that Dijkstra was dumb, is itself dumb. How many Turing awards have you won? Much of the scalability of OOP comes from adopting Dijkstra's principles of structured programming. Far too many OOP proponents don't seem to realize that many of their techniques come from structured programming. This seems to be because they learned OOP without previously knowing about structured programming, and so they incorrectly think that OOD is the origin of these techniques. Furthermore, Dijkstra's quotes usually need to be understood in the context of where and when they were said. I can't find a reference for where or when he said this. That statement could have easily been made in the early 1970's or even the 1960's. OOP has come a long way since then. One of his famous quotes about BASIC was made in 1975, and made a lot of sense then, but wouldn't be terribly fair in the context of Visual Basic of today. --Bill Davidson
        • Dijkstra was brilliant; he was also an asshole. What kind of person makes world-changing contributions to a field and then refuses to use what that field produces? Psychlohexane 08:01, 27 January 2012 (PST)
    • OOP doesn't suck, but a lot of OOP fanboys make it suck by expecting it to be a magical panacea to all problems everywhere. A well-architected procedural application scales just fine, and crappy OOP is impossible to leverage for anything beyond its intended purpose. My professional experience is due to the rise of ".NET communities" there is a lot more bad OOP (.NET) out there than bad procedural. -CppThis
  2. Object oriented programming has been shown to have no significant difference in productivity than standard procderal programming.
    • That's actually just not true.
    • If this "has been shown" then cite the source.

C Sucks

The objections to C appear to amount to "it's old" or "I don't know how to use it." There are maybe three objections in there that may have been written by people who have used C (terribly named functions, preprocessor sucks, switch fall-through). Why not add "you have to compile it" or "it doesn't massage my feet"? Mephistopheles 05:11, 20 April 2012 (PDT)

C's standard supports trigraphs and digraphs. Digraphs were added in C99. Seriously? We're really adding language features (which are more likely to CAUSE bugs than to solve problems) to pander to people who's keyboards don't have [ and ] keys? LadyCailin 13:13, 18 December 2012 (PST)

"The type system in general is useless since you can cast (almost) anything to anything else." -- this is, perhaps, one of C's greatest advantages. The type system will warn you if you don't cast something, pointing out your potential error. But, hey, if you want to turn that pointer into an int and you know what you're doing, you just tell the compiler "cast this to an int". sbrk 10:49, 13 September 2016 (CDT)

C++ sucks? Perhaps not.

Who ever wrote the C++ Part, has no clue about C++ and Compiler Languages! Did you ever imagine that excatly this complexity of C++ made the most language interpreters possible?Tbe 07:01, 16 April 2012 (PDT)

The C++ section should be about five times longer than the PHP section. :-) Matt 15:56, 18 June 2009 (UTC)

I think the reasons for why C++ sucks are vague and in some cases debatable. I would like to see more concrete examples.

  1. C++ doesn't enforce a single paradigm. Neither procedural or object-oriented are enforced resulting in unnecessary complication.
    • Isn't that a good thing?
    • None of the languages on this page enforce a single paradigm. How is this problem specific to C++? --Matt Chisholm
      • Not true: Java enforces object oriented programming (you can't do procedural programming in Java, there are no functions). A71104
        • You absolutely can do procedural programming in Java. Just make all of your methods static. You can even write your entire program in one class. You can be as procedural as you want. Methods that have a return value are really just glorified functions, with the implication that they are attached to an object. However Java's static methods are only attached to a class, not a proper object. Java encourages OOD, but it doesn't really force it. You can write horrible code in Java as easily as with Fortran. -- Bill Davidson
          • There is no notion of class or static in procedual programming because they strictly belong to OO. Therefore, creating a whole Java programm within a static main method is absolutely OO (stupid, but OO). Going on the subjective side of things, I'd say that it is as easy to create horrible code in Java as in Fortran (and any other language, it simply takes an idiot). -- -- User:groovem
  2. It requires a bulky runtime.
    • That's not true. You don't have to use MFC, and you can program really small programs if you turn off function header generation at the linker.
    • What does "bulky" mean? C++'s runtime is lightweight compared to every other language on this page. --Matt Chisholm
      • You're right, I removed that point. --A71104
      • I'd even say the opposite is true: A lot of things one would expect of a standard library these days is not included (list/create/remove directories, unicode support, regular expressions, HTTP client, XML, JSON, ...). There are 3rd party open source libs for that, but I'd expect this to be in the runtime. --Panzi 17:03, 11 April 2012 (PDT)
  3. Not practical for low level system development and quickly becomes a mess for user level applications.
    • That's actually not true. The __asm {} construct allows you to make fairly arbitrary code so long as you tell the compiler to ignore function headers.
      • The GNU __asm {} construct is all but practical. Instead, asm blocks using Intel syntax (which can be found on Microsoft compilers) are much better, but if you are programming in C++ you are not supposed to use much assembly, otherwise you are programming in assembly. --A71104
        • Exactly: you're not supposed to use __asm/asm constructs that much, so the GNU syntax will not get in your way. About being practical or handy, it's mostly a matter of taste. -- jmc
    • Why does it quickly become a mess for user level applications? --Matt Chisholm
      • Because it supports multiple programming paradigms, so a programmer could write object oriented parts and procedural parts, leading to a very heterogeneous and really ugly design, which complicates code maintenance. --A71104
      • Multi-paradigm is possible in pretty much every other language too though, usually through overuse of the local equivalent of static classes/methods. The bigger issue for a large, robust C++ application with many developers is that no garbage collection plus fast-and-loose memory operations leads to things getting forgotten and bad assumptions about what that pointer actually points to, and thus ugly runtime bugs. This no-bullshit efficiency is arguably C++'s biggest selling point, and also its biggest weakness. -CppThis
  4. The standard has no implementation for exception handling and name mangling. This makes cross-compiler object code incompatible.
    • Why does the lack of exception handling make cross-compiler object code incompatible? --Matt Chisholm
      • Not the lack of exception handling, but the lack of any specification that forces an implementation of exception handling; we are talking about *binary* incompatibility. A71104
  5. C++ supports 'goto'.
    • Are we complaining that C++ is too high level or too low level here? Even if it didn't, you could do
    • register int f = *location
    • __asm_ volatile ("jmp eax", "a=", f)
      • Neither of them; we are complaining (as it's widely accepted) that the goto construct brings to really bad designs, and modern languages should just *not* offer such a deadly instrument. A71104
  6. No widely use OS supports the C++ ABI for syscalls.
    • And why should they? The ABI necessitates an underlying operating system (vtables et. al don't appear by magic ya' know), and if C++ enforced them it would make C++ unable to do low level systems programming. Silly.
    • What are you calling "the C++ ABI"? The C++ standard doesn't define such a thing (at all). An ABI is generally characteristic of an operating system and CPU. If you define it in the language, you mandate separation from the OS/hardware, which simply isn't what C++ is intended for.
  7. An std::string::c_str() call is required to convert an std::string to a char*. From the most powerful language ever we would have all appreciated a goddamn overloaded operator const char* () const.
    • I think that this is on purpose. Add such an "operator const char*() const" and the compiler will become confused over the meaning of "str[x]". Is it "str.std::string::operator[](x)" or is it "str.std::string::operator const char*()[x]"? If you desperately need such a thing, just subclass std::string and implement your own operator... -- jmc
      • Keeping both operators would take stupidity to a new level; of course you don't need the [] operator any more when you got the const char* one! --A71104
      • Keeping both operators would mostly raise ambiguity to a new level -- any attempt at using [] would lead to ambiguity, so the code wouldn't compile. The real question here is: why do you want to convert a std::string to a char * in the first place? If you want to do so often enough to care, that's your real problem.Jerry Coffin
  8. There's a moment in every C++ programmer's life where he wonders why, why, switch case fall-through has been invented: it's completely useless, and if you forget a break you introduce a bug silently.
    • How is this exactly related to C++? It's a C idiosincrasy, obviously preserved for backwards compatibility with older C code. It's on purpose: if you don't like it, then head for some other language. -- jmc
      • You're right, I should correct and just write: "C++ is backward compatible with C." That's a huge sucks. :) --A71104
  9. Not to mention a classic: [...]
    Just the same as above, something that should be moved to the "C sucks" section... -- jmc
  10. There is try but no finally
    • Why is that even needed? C++ provides superior alternative, called RAII Idiom. Usage of this idiom results in better code, as it throws irrelevant code outside the function, and then the function can focus on only what it needs to do - the relevant thing. Think of `get` member function of a concurrent queue; using RAII object such as scoped_lock, you can throw lock-unlock responsibility outside the function, and the function can focus on only dealing with the relevant thing - `get` an element from the queue. Also, finally block in other languages result in code duplication which RAII easily avoids. -- Snawaz
      • To state it more succinctly: finally is simply a (mostly failed) attempt at compensating for the lack of deterministic destructors. Since C++ has deterministic destructors, it doesn't need a second-rate imitation.Jerry Coffin
      • If you really need it, you can emulate it: catch (...) { /* do cleanup */ throw; } criptych (talk)
  11. A number of the cited problems are now simply obsolete. C++11 added:
    • native threading support
    • memory model
    • Unicode support
    The first two points are now completely irrelevant. Unicode support could still be better. Jerry Coffin
  12. "Throw in function signatures is perfectly useless."
    In C++11, it's been removed entirely, in favor of the 'noexcept' keyword, which only enforces that the function does not throw. Charles B. (talk)
  13. "The standard committee is unable to establish a memory model and thus add multithreading support, lol."
    This statement is rendered obsolete by C++11. The standard now defines a memory model, and more clearly defines atomics, mutable, and const. Herb Sutter recently did a very good talk on the subject, called "Atomic<> Weapons". Charles B. (talk)
  14. "Lambdas have unique types that cannot be expressed and that makes them very hard to use. For example, standard functions cannot return lambdas."
    This is incorrect. The auto keyword can be used to declare a variable to hold a lambda, and lambdas can be implicitly stored in generic std::function<> objects. Charles B. (talk)
  15. "An std::string::c_str() call is required to convert an std::string to a char*."
    ... The alternative is an operator (const char*)() which gets implicitly called in a number of unexpected places, not all of them desirable. This is why the "Safe Bool Idiom" was invented and why C++11 now has explicit operators. Charles B. (talk)
  16. "What is 's', a function or a variable? std::string s();"
    This is solved in C++11 by encouraging the new {} syntax for this, so you have std::string s{}; which declares an object. Mark VP
  17. "The exception system is not integrated with the platform: dereferencing a NULL pointer will not throw a C++ exception."
    Not throwing an exception when a null pointer is dereferenced, is actually good for performance, which is the main goal of C++. C++ evolves to make it easier to write code in, but never ever at the expense of performance. Mark VP
  18. " Templates are Turing-complete, hence compilers have to solve the halting problem (undecidable) to figure out whether a code will even compile."
    In practice you will never write a template program that doesn't terminate, unless you go really crazy. Long ago I accidentally had it with VC++6, with the only straight forward example I know that doesn't terminate: when a template for T required the same template for T*, creating an infinite loop. But modern compilers immediately stop with an error. Mark VP

Java sucks

  • The assertion: Nearly everything is wrapped with objects and many things must be buffered, even those things that don't really need to be objects or be buffered

must be adequately explained with examples, because it doesn't make much sense: it is left to the programmer whether to buffer something or not. I think that it should be removed. --A71104

  • Exceptions as part of the type system means you have to catch every imaginable exception that might be thrown.
You could just catch java.lang.Exception and let that same type system gobble up the differences. --G H
That's a foolhardy approach which will bite you in the ass eventually - Do you really want to be catching OOM, ThreadAborts, etc? Basic (talk) 10:06, 28 March 2013 (PDT)
Those extend Error and are therefore not an issue if you catch Exception. And in any case, the bytecode you get from a finally block basically catches Throwable. Are you saying we shouldn't use finally either? Trejkaz (talk) 08:28, 20 April 2014 (PDT)
  • Many standard classes do parameter checking and manually throw unchecked exceptions such as NullPointerException and IllegalArgumentException. No problem; but what are the assertions for, then?
Assertions are used to test whether assumptions you make about your own code or that of others hold true. This is different from the two mentioned exceptions in that those signal wrong use of code, not wrong code. For example:
  • You passed in null as a parameter to a method that clearly states in its documentation that this parameter should not be null. It throws an NPE to signal your wrong use.
  • You have an instance field in a class that is not final but should never be null (for example, it must have been set by a container by dependency injection). However, it is. Something isn't doing its work. You catch this abnormality via an assertion.
  • You passed in two differently sized arrays as arguments to a method that states the two arrays must be of the same length. It punishes you with an IllegalArgumentException.
  • You have a piece of code that uses two arrays which you've created at two different places but that should logically have the same length. You test this with an assert. If it fails, it's clear that your code is faulty or you've made a wrong assumption. --G H
It's also explained in the official guide: http://docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html#usage
  • catch clauses can contain only one exception, causing a programmer to rewrite the same code N times if he wants to react the same way to N different exceptions.

This is not true as of Java 1.7: http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html I suggest removing this paragraph

  • The paragraphs:
  • Initialization blocks (both static and non-static) can't throw exceptions.
  • The return statement is not valid within initialization blocks.
  • Instance initialization blocks cannot throw checked exceptions, there must be a no-arg constructor throwing those exceptions in its signature.
That's not why initialization blocks were made. If you want a initialization block that behaves like a method or function, you should take a look at AOP paradigm. I suggest removing this paragraph. -- Rperez 09:17, 21 January 2013 (PST)
  • Arrays are objects but don't properly implement .toString() (if you try to print an array, it just prints hash code gibberish) or .equals() (arrays of the same contents don't compare equal, which causes a headache if you try to put arrays into collections)

I agree with .toString(), but I highly doubt that any programmer would expect(or desire) the equal() method to behave like that on arrays. Why would you want to do that? What would you do, when you already have the arrays in the set and then modify one of them? And what if you don't want one of them to disappear? What if those are vectors for the state machine? One of them disappears. Why? Please, remove the second part of the paragraph.

  • Enums in Java 1.5 are cool, but to use them you have to prefix the enum type, like MyEnum.SomeValue, because they exist in the enum class's namespace, so they are less convenient than just defining int constants

Then don't use them if you don't like them. Enums as a drawback of a Java? Seriously? Saying that enums are less convenient than integer constants is like saying that writing structured code is less convenient than having one method with thousands of code per program.

  • Initialization blocks (both static and non-static) can't throw exceptions

What would that accomplish? See http://stackoverflow.com/questions/2070293/exception-in-static-initialization-block for some explanations on why is that pointless

  • No automatic resource cleanup; instead we get have five lines of "allocate; try {...} finally { cleanup; }"

I may not seeing the point in this paragraph. What resources you mean? Orphaned objects? GC is for that. Closing a file? This is very unclear.

  • No string join function

It's in the apache commons or you can write those three lines of code yourself. Such trivialities only clutter this list. This should be removed.

  • Java has unused keywords, such as goto and const.

I don't see why does it matter. If it's really an issue for some people, then it should be on the bottom of the list.

  • There's int types and Integer objects, float types and Float objects. So you can have efficient data types, or object-oriented data types. Wouldn't it be better to make your object-oriented types efficient?

How exactly is Integer inefficient? Is there some language which handles the same "issue" better? If not, the paragraph should be removed.

-> To me it is inefficient because

 - it is more big in memory: there are store with object signature, which is more big when using arrays (add something like 8 bytes to a value of 4 bytes)
 - Every arithmetic operation on it conduct to be autoboxed into primitive for the operation, then autoboxed again for the result, because of the 'no operator overloading" thing

Clean up

I will clean up the Java section. Here are the reasons for disputed and removed arguments:

disputed

  • Nearly everything is wrapped with objects and many things must be buffered, even those things that don't really need to be objects or be buffered. (examples?)
  • Some interfaces such as Serializable and RandomAccess are used just like annotations: they are empty, and when implemented their only purpose is to indicate some semantics.
    • An interface describes how an object can be used, even if it does not add any methods. From an OO perspective, there is nothing wrong with that.
    • They were introduced before annotations.
    • It is not possible to un-implement the interface, though.
  • Initialization blocks (both static and non-static) can't throw checked exceptions.
    • (Technically false for non-static initialisation blocks - checked exceptions can be thrown if they are declared *by the constructor*. I realise this is not intuitive though, and in itself sucks.) Trejkaz (talk) 08:25, 20 April 2014 (PDT)
  • Arrays are not type safe: Object[] foo = new String[1]; foo[0] = new Integer(42); compiles fine but fails at runtime
    • array covariance exists in other statically typed languages as well
    • Sounds more like complaining that arrays *are* type-safe. It has successfully rejected you putting in a value which is not of the correct type. Trejkaz (talk) 08:25, 20 April 2014 (PDT)
  • Unicode escapes can have unexpected effects, because they are substituted before the code is parsed, so they can break your code, for example: (1) if a line-end comment contains a \u000A (line return), the rest of the comment won't be on the same line, and thus won't be in the comment anymore; (2) if a string literal contains a \u0022 (double quote), it ends the string literal, and the rest of the string is now in the actual code; (3) if a \u appears in a comment, and it is not a valid escape (e.g. "c:\unix\home"), it will cause a parsing error, even though it is in a comment
    • Easily solved by using an IDE with syntax highlighting (or not using unicode escapes).
      • Which IDEs correctly highlight this feature. IDEA is certainly not one of them. Trejkaz (talk) 08:25, 20 April 2014 (PDT)
  • Convenience functions must be overloaded for every fundamental type (e.g. max(float,float), max(double,double), max(long,long))
    • Overloads for long and double are sufficient.
      • But then you will only get longs, even if the original datatype was smaller (e.g. byte).
        This means you will have to convert it back like this: byte foo = (byte)max(value1, value2);
        Which is ugly for obvious reasons.

removed

  • Interface method implementations are necessarily public, preventing to make an interface implementation accessible only to subclasses and same package classes. and You can't inherit a class as protected or private, your classes must publicly show everything they inherit.
  • RuntimeException inherits from Exception, but it doesn't make sense: checked exceptions are a special case of unchecked ones, not the contrary. Otherwise said, if I have to catch all the checked exceptions, why don't I have to catch the unchecked ones?
    • Does make sense, see Liskov Substitution Principle. If CheckedException would extend RuntimeException a method that throws only (unchecked) RuntimeExceptions might also throw checked exceptions. That would be broken. Think of it as every method declaring throws RuntimeException; thus, unchecked exceptions are the special case.
      • I don't see why CheckedException isn't another subclass of Exception though. Sometimes it sucks that we can't catch them separately. I have seen cases where people have caught RuntimeException specifically so that it can be rethrown as-is before catching Exception. 4 lines of code which would be unnecessary if we could just catch CheckedException. Trejkaz (talk) 08:25, 20 April 2014 (PDT)
  • Many standard classes do parameter checking and manually throw unchecked exceptions such as NullPointerException and IllegalArgumentException. No problem; but what are the assertions for, then?
    • assertions are intended for internal consistency checks, can be disabled at runtime, and throw assertion errors. Thus, they must not be used for argument validation-
      • You seem to be talking about a different thing. What the original commenter is saying: When you do no checking, you can get a NullPointerException. Many of the JRE classes introduce specific checking for null, but still throw NullPointerException for some unknown reason. To make matters worse, some of the JRE classes throw IllegalArgumentException for the same condition. I do think the latter is better, but consistency would be nice. Trejkaz (talk) 08:25, 20 April 2014 (PDT)
  • Every, single, object, has its own synchronization monitor, even those that you never synchronize on, resulting in unnecessary resource consumption. If you declare the dummiest ArrayList<Integer>, each element of your array will have a synchronization monitor; and of course you will never synchronize on them. Do you have an idea of how many (totally useless) synchronization monitors there are in an instance of the virtual machine running a medium Java program? And in a big program, such as Eclipse or NetBeans?
    • performance argument is BS. There are zero useless monitors because the VM creates them only when they are needed.
  • Instance initialization blocks cannot throw checked exceptions, there must be a no-arg constructor throwing those exceptions in its signature.
    • Duplicate
  • Can somebody in the universe explain me why the heck the clone method belongs to the Object class instead of the Cloneable interface??
    • Yes, but it's not important. Removed as duplicate to "clone is broken"
  • Cloning is a major pain, because the variable you are cloning must have a type that has a public clone() method (Object's clone() method is protected), which only exists for actual implementation classes, so you can't clone something of an abstract type (which kills abstraction). Also, all the clone() methods in the Java library return type Object for some ungodly reason (instead of the class's own type), so you have to cast it.
    • replaced with link to article
  • Enums in Java 1.5 are cool, but to use them you have to prefix the enum type, like MyEnum.SomeValue, because they exist in the enum class's namespace, so they are less convenient than just defining int constants
    • Enum constants belong to the enum, just like int constants belong to whichever class they are defined in. import static MyEnum.* solves the problem.
  • Wouldn't it be better to make boxed type (Integer, ...) as efficient as the primitives (int, ...)
    • They are as efficient as the value objects in any other OO language
  • No meta-programming.
    • not true.
  • Programmers can be significantly more productive in Python than in Java
    • Source is highly biased, many arguments are disputable. The overall argument of productiveness is a result of the individual points listed above. Productiveness is not the only criterion for a language (or C would be dead by now).

--Tentor (talk) 06:07, 14 October 2013 (PDT)

Ruby sucks

"No real support for arbitrary keyword arguments (key=value pairs in function definitions are positional arguments with default values)"

Not sure what this is supposed to mean. Hashes as the last parameter of a method require no braces:

 def foo(options); end;
 foo(:foo => 'bar', :baz => 'quux')

This requires no order. In 1.9, this can become:

 foo(:foo: 'bar', :baz: 'quux')

Matt 15:51, 18 June 2009 (UTC)

XSLT/XPath sucks?

  • There is no concept of types whatsoever. Everything is fundamentally a string. This means that even things that are intrinsically typed are treated as strings fundamentally. For example, sorting on the number of child nodes sorts by string order, not numeric order, even though counting is an intrinsically numeric operation.
<xsl:sort select="count(*)"/>
<!-- sorts like this: 10, 11, 1, 23, 20, 2, 37, 33, 31, 3, 4, 5, 6, 78, 7, 9 -->
  • <xsl:sort> tag has an optional data-type attribute. It's value could be "text" (this is default), "number" or "qname". So if you want to sort numbers you must set this attribute to "number". --Sandh 18:58, 19 June 2011 (PDT)

Python ** comment removed

For instance, in math -2^2 yields 4, while in Python -2**2 yields -4.

I don't know about you, but I've done Further Maths at A-level and Computer Science with Maths at university, and in absolutely every situation where an expression of the form -xy was involved, it means -(xy); parentheses are used explicitly where the (-x)y meaning is desired. Thus, I've removed this "reason" from the Python section. Keiji 09:18, 17 July 2011 (PDT)

As a fellow mathematics graduate, I concur. — Timwi (talk) 04:46, 9 August 2013 (PDT)

Supports 'goto'

Why would a language supporting a feature you don't have to use make it suck? If it was something like "goto is the only way to idiomatically do x", then fine, but the "goto" keyword simply being there? Mephistopheles 05:24, 20 April 2012 (PDT)

  • +1 -- User:groovem
  • Because you might write crappy code that uses goto, and then I have to maintain it. Granted, if you're just that bad of a programmer, you'll figure out how to write crappy code without gotos, but why would a good language provide a feature that is misused 99.9% of the time, and provides other perhaps slightly less eloquent (but still reasonable) ways of handling the other 0.1%? Besides that, things like goto are noob traps, they use it in a simple program, it works fine, so they assume it scales up to other, more complex situations too, which it won't. LadyCailin 10:24, 3 January 2013 (PST)
  • I think some distinction may be in order here. C and C++ have given “goto” a bad name by making it an incredibly sucky feature. You can use it in ways that will crash your program or make the code make no sense. C# has a “goto” that is completely safe. You cannot use “goto” to jump into a for loop, out of a finally clause, or any crazy shit like that. Such a safe goto is as useful and unsucky a feature as any well-respected standard language feature like while loops or method overloading. — Timwi (talk) 04:39, 9 August 2013 (PDT)

Can we add bash?

Bash is a gold mine of things that suck. That should be a section.

Perl 5 sucks because:

Sigil variance is hugely annoying

  Sigil variance is not annoying..  it is necessary and powerful.  
      my @a = ('a', 'b', 'c', 'd');
      my %h = (a => 1, b => 2, c => 3, d => 4);
      my $c = $a[2];         #  scalar; Third element of the array @a
      my @l = @a[1,3];       #  Array slice; @l contains ('b', 'd'); 
      my $a1 = $h{'a'};      #  scalar; the value of %h associated with the key 'a'
      my @v = @h{'b', 'd'};  # Hash slice; @v contains (2, 4)

hashes don't stay in order like they do in most other languages. This can (and, except for luck, does) mean that reading a JSON string into a data structure and then reencoding it without modifying it except to decode and encode will end up with a different JSON string (even without paying attention to anything that might otherwise muck it up like different character encoding schemes or differences in whitespace used by the encoder).

   That is intentional.  It is a security feature, not an accidental flaw to make someones life complicated.  [1]

just like Ruby it has redundant keyword "unless". You can do "if not" at least in three ways, which can lead to confusion and spoiling readability of code:

    If you don't like unless, don't use it.  Also, the two examples given with '!' and 'not' within an if statement are NOT equivalent.  In the example they
    would work in the same way..  but '!' and 'not' are not just synonyms, and there are subtle differences between the two, namely where the sit in order
    of precedence.

what's with all the $,@,%,& things in front of variables? It takes a lot of effort to type those redundancies every single time ... C and most others let you define a type just once, and then you can use it without reminding yourself what it is. In any case, that Perl lets you change the thing depending on what you want to do so it's even more stupid to use say @ and $ in front of the same var.

  Another complaint about sigils?  They are at the core of perl syntax..  if you don't like them, move on along.  As far as "Perl lets you change the thing depending on what you want to do" goes, I don't get it.  $a, @a, %a, &a..  all refer to the symbol 'a' in the symbol table, but are separate entities.  So, a change to @a has no effect upon the contents of %a, $a, etc.

Not all that sucks

Some of your points are very good but some are just silly. A lot (more than half) of the things you are complaining about were intentional design choices. Also, I can see lack of understanding in some your comments.

I won't comment on everything - just on the 3 languages that I have good opinion about (but my comments are pretty relevant for the other sections too).

Perl 5

  • Sigils are a pretty interesting idea and they are at the core of Perl.
  • Perl has a well-designed type system - you just don't understand how it works. And there's nothing wrong with how Perl uses the dot operator.
  • There's nothing wrong with the regular expression syntax (except probably multi-line handling). It is just poorly explained.
  • You don't understand what hashes are and how do they work.

Python

  • Apparently you don't understand the Python philosophy - there's nothing wrong with the self argument and with lambda function constraints.
  • Tuples are no similar to lists or sets.

C

  • You don't understand what is the purpose of C neither what are the pros/cons of manual memory management.
  • Segmentation faults happen for a reason. Also there are pretty good ways to debug them.

Martinkunev (talk) 16:45, 14 November 2013 (PST)

Hash table order in Perl 5

I've deleted this:

hashes don't stay in order like they do in most other languages. This can (and, except for luck, does) mean that reading a JSON string into a data structure and then reencoding it without modifying it except to decode and encode will end up with a different JSON string (even without paying attention to anything that might otherwise muck it up like different character encoding schemes or differences in whitespace used by the encoder).

Actually, this behavior is exactly like all programming languages. If it remembers the order elements are stored in, it's not a hash. Period. Where the hell did the author get the idea that "most other languages" ever preserve ordering in hashes, even temporarily? - Furrykef (talk) 01:22, 26 March 2014 (PDT)

This page needs some refactoring

It seems like there are lots of old WTFs listed, which aren't up to date anymore. Also, Some sections are not really satisfying in terms of quality of information. e.g. in the section "Why C# sucks", lots of points are not C#-specific, but apply to the whole .NET-runtime. I'm feeling funky today, so I've exported those points into a separate section. I was surprised that there was no "Why VB.NET sucks"-section, so I added one.
There are some points in the "Why C# sucks"-section which I don't agree with. I'll talk about two of them:
1: "Arrays are not type safe: object[] foo = new string[1]; foo[0] = 42; compiles fine but throws at runtime."
Of cause it does. foo may be any Array at all. But by assigning a String-Array to foo, you make it a String-Array (foo.GetType().Name will return "String[]"). You can't put integers into a String-Array, but ther is no way for the compiler to tell, whether or not foo will be a String-Array at runtime. If you still want foo to be an Object-Array, but you want the first Element to be a String, you have to assign an actual Object-Array to foo and assign a String to the first Element:

Object[] foo = new Object[1];
foo[0] = "Hello World";

Here, foo.GetType().Name will return "Object[]".
Then, you can also assign different Objects like new Object(), 4, 3.14 or maybe even new ColaInKeyboardException(), because foo is an actual Object-Array, and not a String-Array.
And 2: "You must null check everything you get since the language allows nulls."
Either I don't understand what the author of this line meant, or we're talking about different things here. Almost every proramming language I know supports "nulls". I assume "nulls" is supposed to be "null-values" or "null-Pointers", and I can't see anything being wrong with that.
The other explanation I can think of is "being able to call instance-Methods on null-Pointers". This was actually a bug in an earlier C#-version. The compiler emitted a "call" instead of "callvirt" for an instance-Method and therefore it was possible to call an instance-Method for a null-Pointer. But this has been fixed. The Compilers (C# and VB) emit only callvirt for instance-Methods. The CLR performs a check for callvirt-instructions, so this is not a problem anymore. However, it is still possible to call instance-Methods on null-Pointers by manually emitting IL and using call instead of callvirt.

C# sucks because of nulls

There is a comment on C#:

You must null check everything you get since the language allows nulls.

How is that bad? It is feature of language, it's by its design. How is that bad design? Plus it is not true for reference types at all.

---

Yeah, that makes no sense. There are non-nullable value types (structs) if you don't want nulls, and you don't have to null-check everything as not everything is going to be null in your program. Also, how can a language have pointers and not have a null pointer?--Hacker-nr1 (talk) 08:30, 20 August 2014 (PDT)

C# ternary operator

See change https://wiki.theory.org/index.php?title=YourLanguageSucks&diff=next&oldid=2750

As of Visual C# 2010, the statement holds up. And I guess it still does in 2012 and 2013: http://stackoverflow.com/questions/4424231/the-type-of-the-conditional-expression-can-not-be-determined

Tested with this snippet:

void foo()
{
    bool condition = false;
    BaseClass a = condition ? new SubClassA() : new SubClassB();
}
class BaseClass { public BaseClass() { } }
class SubClassA : BaseClass { public SubClassA() { } }
class SubClassB : BaseClass { public SubClassB() { } }
  Der Typ des bedingten Ausdrucks kann nicht bestimmt werden, weil keine implizite Konvertierung zwischen "SubClassA" und "SubClassB" erfolgt.
  Type of conditional expression cannot be determined because there is no implicit conversion between 'SubClassA' and 'SubClassB'

So I suggest re-adding this line. Unfortunately, no comments were supplied for the change (at least I didn't find them).

Scala

What's wrong with <- syntax? It's totally ok.

COBOL

Apparently COBOL does not suck

Clojure

I disagree with the second bullet point. Clojure is compiled to byte-code, same as Java and executed on a VM that's generally quite high-performance. Hotspot does a lot of optimisation, for example things like intrinsics replace some functions (e.g. maths) with native code. And immutable program design can help avoid locking issues.

- Reply:

You are right (now i've fixed this point in the page) , "interpreter" is not the right word to define what clojure does since when you write clojure code it's like you are using placeholders for real java code and when you compile they are replaced with real calls to the clojure core and then the result is compiled in java bytecode, so, clojure is translated in java and compiled.

Java already uses native code for math. If i'm not wrong clojure doesn't have native code at all, it's pure java compiler/interpreter ( https://github.com/clojure/clojure ) this means that the only native code it uses is from java standard libraries.

Forcing people to use immutable objects is not the right way to avoid loking issues, mutable objects exists because developers need them. Immutable program design is just a thing that makes clojure software slow and memory greedy. Anyway java supports them as well.

And if you still believe that clojure is as fast as java or even faster (that's quite funny since it's itself a java software) just look at this byte code rappresentation obtained with javap


   Compiled from "Hello.java"
   public class Hello {
       public Hello();
           Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
       public static void main(java.lang.String[]);
           Code:
           0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
           3: ldc           #3                  // String Hello World
           5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
           8: return
   }

This is an hello world in java, now write an hello world in clojure, compile it and then get its bytecode. You won't even know on which file run javap since clojure "compiler" generates a lot of classes just for a damn simple program.

Flex/ActionScript

It sucks because of so many things, but not for having String final (it is the same in Java and it's ok to me)

it sucks because of:

- AMF protocol when using server: binary, specific to Flash, unusable with another technology
- CSS: CSS are just not CSS in Flex, not the same attributes, not the same values, and not really cascading.
- Strange API names: to be precised, but the name are different from a component to another

Julia

About time to include it in here.

Rust

About time to include it in here.