YourLanguageSucks
From TheoryOrg
Contents |
CSS sucks because:
- Hello? Rounded corners? Mac OS had them in 1994.
- Can only set one background image.
- Just too many ways to say the same thing.
- Can't specify stretchable background images.
- text-align:justify really means "left justify". No way to right justify or center justify.
- No way to make vertical or angled text.
- No way to vertically align block elements.
- Horizontally aligning block elements was not intended to be supported and is only hackish at best.
- Can float an item to the left or the right. But you cannot float items to the center.
- float is only horizontal; there is no equivalent vertical operation.
- Similarly, there is no vertical equivalent to clear.
- No way to modularize or programmatically generate colors. If you want text and borders to use the same color, you have to write that color twice.
- No way to modularize or programmatically generate lengths. Can't say:
{ width:50% - 2px; }
- The CSS spec is contradictory with regard to identifiers:
- The syntax says that identifiers don't allow uppercase characters anywhere but in the first character:
- ident {nmstart}{nmchar}*
- nmstart [a-zA-Z]|{nonascii}|{escape}
- nmchar [a-z0-9-]|{nonascii}|{escape}
- Section "4.1.3 Characters and case:" says:
- In CSS2, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [A-Za-z0-9] and ISO 10646 characters 161 and higher, plus the hyphen (-); they cannot start with a hyphen or a digit."
- The syntax says that identifiers don't allow uppercase characters anywhere but in the first character:
- *Why* diverge from the standard identifier format, [a-zA-Z][a-zA-Z0-9_]*, which has been in use since the 1970s?
- It still sucks that CSS 2 didn't have these, even though they're being added in CSS 3:
- Gradients?
- Transparency?
Python Sucks because:
- The syntax for singleton tuples,
(x,), is confusing, and different from the syntax for singleton lists:
(1) == 1 # (1) is just 1 [1] != 1 # [1] is a singleton list (1,) != 1 # (1,) is a singleton tuple (1) + (2) != (1,2) # (1) + (2) is 1 + 2 = 3 [1] + [2] == [1,2] # [1] + [2] is a two-element list (1,) + (2,) == (1,2) (1, + 2,) == (1,2) # 1, is the same as (1,) (1,2) + (3,4) == (1,2,3,4)
- default values for optional, key-word arguments are evaluated at parse-time, not call-time
- No labeled break or continue
PHP Sucks because:
-
'0',0, and0.0are false, but'0.0'is true -
NULLis not false -
__toString()on php5 objects only gets called forprint()andecho(), not concatenating or casting - There is no one consistent idea of what a expression is. There are at least three: normal, plus the following exceptions:
-
Array()can not be put in function calls - here doc syntax
"<<END"can not be used in the initiation of method attribute default values
-
- There is no way to find if vars hold refs to the same object. (well since
__toString()is broken I guess you could do((string) $obj1) == ((string) $obj2)but that is stupid.) - The documentation is not versioned. There is a single version of the docs that you are supposed to use for php4.x, php5, php5.1... It is often up to you to figure out when features were added if they forget to mention it.
- There is no general concept of an identifier. Some identifiers (like variable names) are case sensitive, others case insensitive (like function calls):
$x = Array(); $y = array(); $x == $y; # is true $x = 1; $X = 1; $x == $X; # is false
- if you mis-type the name of a built-in function, no error is raised; instead, it is interpreted as a string "nonexistent_function_name."
- if you send the wrong number of arguments to a function call, no error is raised; the extra arguments are ignored.
-
foreach()over an empty Array raises a warning. WTF? (compare to previous two points) -
Array()is a hash & array in one data type - fatal errors do not include a traceback or stack trace.
- it doesn't have dynamic scoping
- there's no None or undef type/value
- it has identifier auto-vivification with no equivalent of
"use strict" - in addition to implementing POSIX STRFTIME(3), roll-your-own date formatting language.
- order of parameters to mktime is totally random: mktime(hour, minute, second, month, date, year)
-
07 == 7,07 != 0,08 == 0,08 != 8 - weakass string interpolation resolver:
error_log("Frobulating $net->ipv4->ip");
Frobulating Object id #5->ip
$foo = $net->ipv4;
error_log("Frobulating $foo->ip");
Frobulating 192.168.1.1
- OMFG, it's stupid.
- How stupid? *This* stupid:
#define HASH_KEY_NON_EXISTANT
XSLT/XPath sucks because:
- It starts numbering from 1. Unlike *every single other* major programming language in use today. Unlike the XML DOM.
- XPath has date maniuplation functions to get the second, minute, hour, date, month, and year from a date-time. But it has no function to get the day of the week, so it's completely useless.
- There is no way to modularize or abstract any XPath expressions, resulting in lots of copied and pasted code.
- conditionals in
test=""attributes of<xsl:if>and<xsl:when>items. - sorting conditions in
<xsl:sort>
- conditionals in
- When your context is the contents of a node-set, the
key()functions defined on the entire input XML do not work. What's dumber, no error message is produced; yourselect="key(...)"just silently returns the empty set. It should at least say "key() does not work inside node-sets" or perhaps "no such key in context node-set" - The
select="",value=""andmatch=""attributes do basically the same thing. And their use is arbitrarily exclusive; you must use the correct attribute in the correct place, and if you use the wrong one, the node fails without any warning. These three attributes should have the same name. - If you import a function (like
str:replace()) but fail to import it correctly or fully (like leaving off the namespace), and then call that function, no error is raised whatsoever. The function simply evaluates to it's last argument. How could this ever be desirable behavior? If I'm calling a function that's somehow not available, obviously that is always a programmer error, and some warning should be raised. - There's no way to construct a custom set of values and then iterate over it at runtime, although there is a way to construct a single custom value and then operate on it at runtime. In other words, the language has no list/array/tuple/dict/hash/set/iterable/collection type.
- It allows '-' in identifiers, but the parser isn't smart enough to figure out when you mean 'minus' instead of - . If you're going to allow '-' as an identifier character and as an operator, at least make it so that the string following the identifier character '-' has to follow the standard identifier pattern,
[a-zA-Z_][a-zA-Z0-9_]*. Don't make this one use of whitespace significant in a language where whitespace is usually insignificant around operators. Nobody is ever going to want a variable name like$foo-100, because it looks just like $foo - 100.-
$foo-baris rightly interpreted as a variable name -
$foo - 100is rightly interpreted as subtraction -
$foo+100and$foo + 100are rightly interpreted as addition -
$foo-100is wrongly interpreted as a variable name
-
- 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 -->
- There are too many levels of syntactic and semantic interpretation:
- Parse XML syntax (ensure that all nodes are closed, etc)
- Parse XSL syntax (ensure that nodes that must be under/contain other nodes are present, verify that all xsl:foo node names are valid, etc)
- Parse XSL semantics (find the correct attributes under each node type, etc)
- Parse XPath syntax (entirely contained inside attribute values, cannot be parsed earlier)
- Parse XPath semantics
JavaScript sucks because:
- If you have an event handler that calls alert(), it always cancels the event, regardless of whether you want to cancel the event or not
// This event handler lets the event propagate
function doNothingWithEvent(event){
return true;
}
// This event handler cancels propagation
function doNothingWithEvent(event){
alert('screwing everything up');
return true;
}
- Automatic type conversion between strings and numbers, combined with '+' overloaded to mean concatenation and addition. This creates very counterintuitive effects if you accidentally convert a number to a string:
var i = 1; // some code i = i + ""; // oops! // some more code i + 1; // evaluates to the String '11' i - 1; // evaluates to the Number 0
- Passing the wrong number of arguments to a function? No problem, it just ignores them!
function foo(array1, array2){
/* do something */
}
foo([1,3,4], 4,5,6,7); /* Whoops! forgot my []s */
Object-oriented programming sucks because:
This section has been disputed on the discussion page.
- "Object-oriented programming is an exceptionally bad idea which could only have originated in California." --Edsger Dijkstra
- Object oriented programming has been shown to have no significant difference in productivity than standard procderal programming.
C++ sucks because:
Some points in this section have been disputed on the discussion page.
- C++ doesn't enforce a single paradigm. Neither procedural or object-oriented paradigms are enforced, resulting in unnecessary complication.
- It requires a bulky runtime.
- The specification has grown to over 600 pages, which reflects the bulky nature of C++.
- Not practical for low level system development and quickly becomes a mess for user level applications.
- The standard has no implementation for exception handling and name mangling. This makes cross-compiler object code incompatible.
- The nature of C++ has led developers to write compiler dependent code, creating incompatiblity between different compilers and even different versions of the same compiler.
- No widely used OS supports the C++ ABI for syscalls.
- C++ supports 'goto'.
Java sucks because:
- Exceptions as part of the type system means you have to catch every imaginable exception that might be thrown. This makes it hard to rapidly prototype or quickly test out several methods of solving a problem.
- Functions in the standard library do not use consistent naming, acronym and capitalization conventions, making it hard to remember exactly what the items are called:
-
java.nethasURLConnectionandHttpURLConnection: why notUrlConnectionorHTTPURLConnectionorHttpUrlConnection? -
java.utilhasZipOutputBufferandGZIPOutputBuffer: why notZIPOutputBufferorGnuZipOutputBufferorGzipOutputBufferorGZipOutputBuffer?
-
- Everything is in objects and must be buffered, even those things that don't really need to be buffered or in objects.
- There's
inttypes andIntegerobjects,floattypes andFloatobjects. So you can have efficient data types, or object-oriented data types. Wouldn't it be better to make your object-oriented types efficient?
Ruby sucks because:
-
String.downcase? Who calls it "downcase?" It's called "lower case," and the method should be called "lowercase," "lower," or even "toLowerCase." AndString.upcaseshould have been called "uppercase," "upper," or even "toUpperCase." - Unicode support should have been built in from 1.0, not added after much complaining in 1.9/2.0 in 2007
- No support for negative / positive look-behind in regular expressions in 1.8
- Regular expressions are always in multi-line mode
- No real support for arbitrary keyword arguments (key=value pairs in function definitions are positional arguments with default values)
- The documentation is not versioned.

