What is, in your opinion, the most surprising, weird, strange or really "WTF" language feature you have encountered?

Please only one feature per answer.

link|flag
20  
according to user's answers seems that the winner is JavaScript :) – Noya Jul 21 at 15:32
46  
You know, this thread is awesome for anyone designing a new programming language. – Rei Miyasaka Aug 6 at 19:42
2  
@Rei Miyasaka: Better yet, combine all these "features" into a single language. Now that's how brainf*ck should have been written. ^^ – gablin Sep 19 at 21:05
5  
@gablin I think if you combined LISP delimiters with PERL regex using javascript parsing you would cover 90% of the WTF... – Talvi Watia Sep 19 at 23:41

325 Answers

1 2 3 4 5 11

In C, arrays can be indexed like so:

a[10]

which is very common.

However, the lesser known form (which really does work!) is:

10[a]

which means the same as the above.

link|flag
53  
Oh, my. this is my very first to see this feature. It's really a WTF to me. – yehnan Jan 3 at 14:46
557  
that's because a[10] means *(a+10) ... and 10[a] means *(10+a) :) – Michel Kogan Jan 3 at 14:50
50  
Don't forget "Hello World"[i]. Or i["Hello World"] – Richard Pennington Jan 3 at 15:12
127  
Or, more usefully, "0123456789abcdef"[x & 0xf] – Dipstick Jan 3 at 15:33
94  
I've been waiting a long time to find a question where this little bit of trivia would come in handy :) – Edan Maor Jan 3 at 15:56
show 17 more comments

In JavaScript:

 '5' + 3 gives '53'

Whereas

 '5' - 3 gives 2
link|flag
58  
I remember when I first started using javascript using this sort of technique to add numbers in strings: "111" - -"222" gives 333 whereas "111" + "222" gives "111222". – Callum Rogers Jan 3 at 16:03
92  
+ for string concatenation is horrible – kemp Jan 3 at 16:42
274  
+ for concat isn't the problem. Weak typing is. – FogleBird Jan 3 at 21:18
200  
@FogleBird Neither one is really the problem. It's just the combination of the two with inconsistent coercion rules. – TM Jan 3 at 21:29
49  
So basically, + is concat when a string is involved. Why can't they code something like '123456' - 456 = '123'? That would be interesting. – Jimmie Lin Jan 4 at 8:40
show 28 more comments

In JavaScript, the following construct

return
{
    id : 1234,
    title : 'Tony the Pony'
};

returns undefined is a syntax error due to the sneaky implicit semicolon insertion on the newline after return. The following works as you would expect though:

return {
    id : 1234,
    title : 'Tony the Pony'
};

Even worse, this one works as well (in Chrome, at least):

  return /*
*/{
    id : 1234,
    title : 'Tony the Pony'
  };

Here's a variant of the same issue that does not yield a syntax error, just silently fails:

return
    2 + 2;
link|flag
30  
Now this is a good example. – ChaosPandion Jan 5 at 0:37
155  
Semicolon insertion is one of the most evil parts of JavaScript. – fennec Jan 5 at 1:17
145  
You always run into problems when you design language features around the assumption that your users will mostly be idiots. – Rob Van Dam Jan 5 at 6:38
103  
Ya gotta love that: commenting out invisible code! – RCIX Jan 5 at 12:57
70  
Awesome feature! A+++ would program again! – Will Jan 5 at 15:07
show 23 more comments

JavaScript truth table:

''        ==   '0'           //false
0         ==   ''            //true
0         ==   '0'           //true
false     ==   'false'       //false
false     ==   '0'           //true
false     ==   undefined     //false
false     ==   null          //false
null      ==   undefined     //true
" \t\r\n" ==   0             //true

Source: Doug Crockford

link|flag
169  
Good thing Javascript has the === operator, then. – Anonymous Jan 4 at 10:16
40  
So what purpose does == serve in the eyes of the language designer? – Chris S Jan 4 at 15:20
86  
Confusing people. – Javier Badia Jan 4 at 16:19
12  
@Chris S: I think it's supposed to do what people expect most of the time. – cdmckay Jan 4 at 16:26
78  
It'd be nice if == had the meaning of ===, and then there was another operator, something like ~= that allowed type coercion. – TM Jan 4 at 22:39
show 16 more comments

Trigraphs in C and C++.

int main() {
   printf("LOL??!");
}

This will print LOL|, because the trigraph ??! is converted to |.

link|flag
53  
Quick! Tell all C /b/ programmers! – voyager Jan 3 at 20:39
166  
Trigraphs are amazing, because you can be sure nobody will -ever- find out what ??! will mean from Google without knowing the name already. – zaratustra Jan 4 at 4:47
40  
Trigraphs are disabled by default in GCC. – jetxee Jan 4 at 21:12
260  
These let you use the "WTF operator": (foo() != ERROR)??!??! cerr << "Error occurred" << endl; – user168715 Jan 4 at 21:39
34  
Trigraphs were a necessary evil when they were introduced. Some platforms just did not include certain characters key to the language, so it was either "trigraphs" or "you can't have a C compiler period-end-of-statement so go use assembler". Check out Stroustrup's description in "The C++ Programming Language". – Euro Micelli Jan 5 at 3:31
show 21 more comments

Fun with auto boxing and the integer cache in Java.

Integer foo = 1000;
Integer bar = 1000;

foo <= bar; // true
foo >= bar; // true
foo == bar; // false

//However, if the values of foo and bar are between 127 and -128 (inclusive)
//the behaviour changes:

Integer foo = 42;
Integer bar = 42;

foo <= bar; // true
foo >= bar; // true
foo == bar; // true

Explanation

A quick peek at the java source code will turn up the following:

/**
     * Returns a <tt>Integer</tt> instance representing the specified
     * <tt>int</tt> value.
     * If a new <tt>Integer</tt> instance is not required, this method
     * should generally be used in preference to the constructor
     * {@link #Integer(int)}, as this method is likely to yield
     * significantly better space and time performance by caching
     * frequently requested values.
     *
     * @param  i an <code>int</code> value.
     * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
    }

Note: IntegerCache.high defaults to 127 unless set by a property.

What happens with auto boxing is that both foo and bar the same integer object retrieved from the cache unless explicitly created: e.g. foo = new Integer(42), thus when comparing reference equality, they will be true rather than false. The proper way of comparing Integer value is using .equals;

link|flag
27  
Took me a couple of seconds to see why... java must keep a pool of Integer instances for values between -128 and 128, otherwise it allocs a new Integer, right? – Mike Akers Jan 4 at 20:25
16  
however keep in mind that if you specify new Integer(42) it will not be using the instance from the pool so foo == bar will evaluate to false – yx Jan 4 at 20:58
11  
174  
So glad I'm a C# programmer. – Will Jan 5 at 15:06
59  
@Will: C# has some very similar gotchas. See blogs.msdn.com/jmstall/archive/2005/03/06/386064.aspx – spookylukey Jan 7 at 11:08
show 26 more comments

Quoting Neil Fraser (look at the end of that page),

try {
    return true;
} finally {
    return false;
}

(in Java, but behaviour is apparently the same in JavaScript and Python). The result is left as an exercise to the reader.

EDITED: As long as we are on the subject consider also this:

try {
    throw new AssertionError();
} finally {
    return false;
}
link|flag
26  
+1. For some reason, I find this hilarious and can't stop giggling. – outis Jan 5 at 15:25
107  
Thankfully C# doesn't allow such madness... Control cannot leave the body of a finally clause – Richard Ev Jan 5 at 16:40
40  
This returns, false, does it? It may look like a WTF (and possibly it is one), but I live by the rule: Finally always wins, unless you crash the Machine before. – Michael Stum Jan 5 at 19:01
22  
To be fair, I blame TDWTF's nice explanation for remembering that finally always wins unless you yank the power cord: thedailywtf.com/Articles/My-Tales.aspx – Michael Stum Jan 6 at 2:10
12  
I'm not sure what the code should return in this case. But I'm absolutely sure that you must not put return in finally clause. – J.F. Sebastian Jan 6 at 20:31
show 20 more comments

APL (other than ALL of it), the ability to write any program in just one line.

e.g. Conway's Game of Life in one line in APL:

alt text

If that line isn't WTF, then nothing is!

And here is a video

link|flag
16  
I love APL. Ah, the joys of spending an entire afternoon to write half a line of code! The first thing I'll do when I get a keyboard where I can program what letters are displayed is to reacquaint myself with APL again. – Daniel C. Sobral Jan 5 at 16:20
13  
Looks like a language for Greeks. – Esko Jan 5 at 23:32
31  
@Erik: There's joy to be found in writing code which is solely about what you want, and not about how to get there. Of expressing your code as a single expression. It's like the ultimate perfect katana cut. Of course, in a real fight I'd rather have a gun. – Daniel C. Sobral Jan 7 at 18:38
7  
APL is designed to be written, not read. – lkessler Jan 12 at 3:15
56  
APL would be awesome to see in a sci-fi action movie. I can imagine someone sitting at a three-color terminal muttering "Reshape the enemy missile vector...transpose...pi times logarithm...grade up--and--execute!" followed by explosions and cheering. – Joey Adams Jan 16 at 0:07
show 8 more comments

PHP's handling of numeric values in strings. See this previous answer to a different question for full details but, in short:

"01a4" != "001a4"

If you have two strings that contain a different number of characters, they can’t be considered equal. The leading zeros are important because these are strings not numbers.

"01e4" == "001e4"

PHP doesn’t like strings. It’s looking for any excuse it can find to treat your values as numbers. Change the hexadecimal characters in those strings slightly and suddenly PHP decides that these aren’t strings any more, they are numbers in scientific notation (PHP doesn’t care that you used quotes) and they are equivalent because leading zeros are ignored for numbers. To reinforce this point you will find that PHP also evaluates "01e4" == "10000" as true because these are numbers with equivalent values. This is documented behaviour, it’s just not very sensible.

link|flag
43  
Just use === and !==. Which should be used anyway unless a loose type comparison is needed. – Dykam Jan 3 at 16:52
10  
@Dykam, if you follow the link to the fuller answer you'll see that I've addressed the use of the === operator. – Dan Dyer Jan 3 at 17:17
12  
Weak typing strikes again! – rotard Jan 6 at 22:50
2  
+1 ... WTF? Good to know this. – frunsi Jan 6 at 23:51
27  
I always knew PHP was a sin. Up until now I didn't realize it was an unforgivable sin :D – trinithis Feb 13 at 12:08
show 9 more comments

Perl's many special variables

$.
$_
$_#
$$
$[
@_

They're definitely shorter than the equivalent, but if you subscribe the school of thought that you write code for humans rather than trying to impress the computer then it makes reading the code for a non-Perl veteran a lot harder.

Read the complete list here

link|flag
59  
The $[ variable is the most evil of them all. – Brad Gilbert Jan 4 at 4:34
18  
Would definitely appreciate it if Perl 6 was something I could code in without having to check perldoc perlvar every five seconds. (Though I confess that half the time I check it thinking "I know there's a special variable that can do this for me, I just don't remember which one..." =P ) – Chris Lutz Jan 4 at 7:26
8  
@Lutz: use English;, but don't blame me if you get strange looks. – Anonymous Jan 4 at 10:08
12  
The problem with use English; is that it affects RegExp performance. I am not making this up. perldoc.perl.org/English.html#PERFORMANCE – Dave Webb Jan 4 at 13:06
11  
@Dave: it's not a problem because of the -no_match_vars option in the page you linked. @Brad: $[ is SO evil. The intention behind it is evil, yes, but it also doesn't even work! @Artem: from perlvar "Perl identifiers that begin with digits, control characters, or punctuation characters are exempt from the effects of the package declaration and are always forced to be in package main ; they are also exempt from strict 'vars' errors." So that means @$ would be created and assigned to without an error even under stricture. Ugh! – rjh Jan 5 at 3:03
show 20 more comments

Let's have a vote for all languages (such as PL/I) that tried to do away with reserved words.

Where else could you legally write such amusing expressions as:

IF IF THEN THEN = ELSE ELSE ELSE = THEN

(IF, THEN, ELSE are variable names)

or

IF IF THEN THEN ELSE ELSE

(IF is a variable, THEN and ELSE are subroutines)

link|flag
11  
I really laughed out loud when reading this... +1 – The King Jan 7 at 12:48
86  
buffalo buffalo buffalo buffalo buffalo buffalo buffalo. (See Wikipedia if you don't get the reference.) – quark Jan 7 at 19:37
9  
@quark, you're missing a buffalo – RoadieRich Jan 11 at 22:35
11  
@RoadieRich one group of buffaloes is not explicitly from Buffalo, they are just nondescript buffalo. – jae Jan 12 at 2:24
9  
John where James had had had had had had had had had had had a better effect on the teacher. – GameFreak Jul 21 at 17:18
show 7 more comments

The JavaScript octal conversion 'feature' is a good one to know about:

parseInt('06') -> 6
parseInt('07') -> 7
parseInt('08') -> 0
parseInt('09') -> 0
parseInt('10') -> 10

More details here.

link|flag
36  
Got stuck on a bug that all the numbers worked except 8 and 9!! Was going crazy!!! Thanks Brian! – Faruz Jan 6 at 6:12
7  
@Yada Don't you mean octal? Hexadecimal is 0x. – luiscubal Jan 6 at 22:43
34  
And that's why parseInt takes an (optional) extra argument :). – LiraNuna Jan 7 at 5:18
7  
leading 0 means octal number. since 8 is not a valid octal digit, the result must be 0. – devio Jan 7 at 16:07
12  
... and parseInt('010') -> 8 just to confuse you. – Richard Gadsden Jan 15 at 15:33
show 10 more comments

The weird things C++ templates can be used for, best demonstrated by "Multi-Dimensional Analog Literals" which uses templates to compute the area of "drawn" shapes. The following code is valid C++ for a 3x3 rectangle

#include"analogliterals.hpp"
using namespace analog_literals::symbols;

          unsigned int c = ( o-----o
                             |     !
                             !     !
                             !     !
                             o-----o ).area;

Or, another example with a 3D cube:

  assert( ( o-------------o
            |L             \
            | L             \
            |  L             \
            |   o-------------o
            |   !             !
            !   !             !
            o   |             !
             L  |             !
              L |             !
               L|             !
                o-------------o ).volume == ( o-------------o
                                              |             !
                                              !             !
                                              !             !
                                              o-------------o ).area * int(I-------------I) );
link|flag
7  
While Eelis' analog literals are great, are they a strange language feature, or just a strange way to use a feature? – Roger Pate Jan 10 at 9:02
37  
The real WTF will be the compiler error generated by one of those that is malformed. – Andrew McGregor Jan 20 at 12:10
24  
+1 Finally I dont have to put my ascii drawings in comments =) – Viktor Sehr Mar 1 at 22:18
3  
How sick is that..wake me up again when there is a version of AnalogLiterals that supports turning the literal around the X, Y and Z axis in Eclipse...now that would give "visual programming" a new real meaning. – TheBlastOne Aug 17 at 14:23
1  
Do the ordering of the o's and L's and |'s matter? – SHiNKiROU Sep 4 at 17:47
show 2 more comments

Algol pass by name (illustrated using C syntax):

int a[3] = { 1, 2, 3 };
int i = 1;

void f(int j)
{
    int k;
    k = j;  // k = 2
    i = 0;
    k = j;  // k = 1 (!?!)    
}

int main()
{
    f(a[i]);
}
link|flag
22  
If you think about it, it actually makes some sort of twisted sense – RCIX Jan 3 at 15:52
26  
If I thunk about it, you're right. ;-) – Richard Pennington Jan 3 at 17:02
68  
This is the ultimate "pass by reference". – Dykam Jan 3 at 17:20
7  
So this is something like ... template<typename T> struct by_name { virtual operator T&() = 0; }; void f(by_name<int> j) { ... } int main() { f(struct : by_name<int> { operator int&() { return a[i]; } }); }? – Simon Buchan Jan 5 at 10:38
26  
Scopefail....... – Will Jan 5 at 15:09
show 17 more comments

In Java:

int[]  numbers() {
  return null;
}

Can be written as:

int  numbers() [] {
  return null;
}
link|flag
15  
Wow! I wish I could be a fly on the wall when that array syntax was designed! – Adam Paynter Jan 4 at 17:25
23  
I hate to say this but the WTF one is a consistent extension of the C type system. If C functions were allowed to return arrays then that's what it would look like. The nicer one is a consistency violation to make it more readable. Much like "const char * var" vs "char const * var". – tolomea Jan 4 at 22:38
11  
@Adam - It actually makes sense when you consider that variable declaration similarly allows both "int stuff[]" and "int[] stuff". They just let the same rules work for method declaration. – CaptainAwesomePants Jan 5 at 0:06
2  
@lImbus: Actually, const T* and T const* are equivalent, it's T* const that consts the pointer. Also, I hate sans fonts. – Simon Buchan Jan 5 at 10:42
2  
After all, numbers()[2] is a legal statement. – badp Feb 9 at 16:53
show 3 more comments

Duff's device in C!

In C one can interlace a do/while with a switch statement. Here an example of a memcpy using this method:

void duff_memcpy( char* to, char* from, size_t count ) {
    size_t n = (count+7)/8;
    switch( count%8 ) {
    case 0: do{ *to++ = *from++;
    case 7:     *to++ = *from++;
    case 6:     *to++ = *from++;
    case 5:     *to++ = *from++;
    case 4:     *to++ = *from++;
    case 3:     *to++ = *from++;
    case 2:     *to++ = *from++;
    case 1:     *to++ = *from++;
            }while(--n>0);
    }
}
link|flag
6  
Duff's device is probably a good reason for the switch statement not having a break by default ;-) However, I did not yet see any other good use of interlaced switch and loop - but probably there is one. Oh wait, yes, there is another use: coroutines and protothreads. – frunsi Jan 7 at 19:14
13  
@frunsi: "Duff's device is probably a good reason for the switch statement not having a break by default" - Always make the common case the default. I would not exactly say this is the common case.. – BlueRaja - Danny Pflughoeft Jan 19 at 20:14
6  
@mcv probably easiest if you try to read it as assembly code, i.e. the while at the end is a (conditional) JMP back to the do, which explains why you can skip the do and still end up in the loop. – wds Jan 22 at 9:01
9  
Do keep in mind that Duff's Device generally produces WORSE code than the normal looping statement for modern compilers, which know how to (better) loop unrolling than you can do by hand. – Billy ONeal Feb 8 at 17:54
18  
@frunsi: Duff himself, publishing it, claimed something like this: "This definitely provides an argument in the discussion whether switch should fall through by default, but I'm not sure if the argument is for or against it." – SF. Feb 26 at 13:58
show 11 more comments

INTERCAL is probably the best compendium of strangest language features. My personal favourite is the COMEFROM statement which is (almost) the opposite of GOTO.

COMEFROM is roughly the opposite of GOTO in that it can take the execution state from any arbitrary point in code to a COMEFROM statement. The point in code where the state transfer happens is usually given as a parameter to COMEFROM. Whether the transfer happens before or after the instruction at the specified transfer point depends on the language used. Depending on the language used, multiple COMEFROMs referencing the same departure point may be invalid, be non-deterministic, be executed in some sort of defined priority, or even induce parallel or otherwise concurrent execution as seen in Threaded Intercal. A simple example of a "COMEFROM x" statement is a label x (which does not need to be physically located anywhere near its corresponding COMEFROM) that acts as a "trap door". When code execution reaches the label, control gets passed to the statement following the COMEFROM. The effect of this is primarily to make debugging (and understanding the control flow of the program) extremely difficult, since there is no indication near the label that control will mysteriously jump to another point of the program.

link|flag
13  
Quite evil -- turns labels into GOTOs. Sounds like a language feature hackers would beg for... – RCIX Jan 3 at 15:52
7  
it's like the GOTO for AOP... – RCIX Jan 4 at 8:10
85  
Ok, but INTERCAL is supposed to be funny - this is not really a surprising "gotcha". INTERCAL compiler can actually refuse to compile the program if you don't use the PLEASE modifier often enough! – Groo Jan 4 at 10:54
5  
Sounds like AOP :) – Adrian Jan 5 at 0:11
4  
What amazes me most is that in system requirement analysis in the "World of Commercial T. I." , COMEFROMs are actually used in text files describing Use Cases. (seriously: some analysts here delayed a corporate wide migration to OpenOffice instead of MS's Office because the former could not properly reference a "comefrom" with the required granularity in a link) – jsbueno Jan 6 at 17:50
show 10 more comments

In Python:

>>> x=5
>>> 1<x<10
True
>>> 1<x<3
False

Not a WTF, but a useful feature.

link|flag
133  
I wish every other language has this feature – vava Jan 4 at 8:33
22  
As with pretty much every cool Python feature, it looks like Guido just ALGOL-ized the syntax of a cool Lisp feature. :-) – Ken Jan 4 at 16:49
14  
Also, it evaluates just once, so (funct_a(5)+5 > b > funct_a(5)) only calls funct_a(5) once. It's a GREAT feature! – Khelben Jan 4 at 21:45
31  
I wouldn't call this a strange feature though.. – corymathews Jan 4 at 21:47
35  
@Khelben: No, funct_a will be called twice in that example. In b > funct_a(5) > c it will only be called once though, as opposed to b > funct_a(5) and funct_a(5) > c. – Baffe Boyois Feb 4 at 6:31
show 16 more comments

Not really a language feature, but an implementation flaw: Some early Fortran compilers implemented constants by using a constant pool. All parameters were passed by reference. If you called a function, e.g.

f(1)

The compiler would pass the address of the constant 1 in the constant pool to the function. If you assigned a value to the parameter in the function, you would change the value (in this case the value of 1) globally in the program. Caused some head scratching.

link|flag
94  
Ooh. Then 2+2 can equal 5 (for very large values of 2 of course!). – Alok Jan 3 at 21:14
5  
Obligatory TDWTF link: thedailywtf.com/Articles/The-Integer-Cache.aspx – Tom Jan 4 at 20:21
12  
um, what value of 2 would make "2+2" == "5"? I don't know any integer value 2 can take on for that to be true. – Aaron Jan 4 at 21:07
33  
@earlz: I suspect that it would wind up as an integral value, of whatever bit pattern. On the other hand, you could probably set 5 to 4 that way (so 2+2 would equal 5 for small values of 5). – David Thornley Jan 4 at 22:17
15  
Excuse me, Alok, but this is early FORTRAN we're talking about. It won't be true that 2 + 2 = 5; that'll be a syntax error. What will be true is 2 + 2 .EQ. 5. – David Thornley Jan 6 at 15:57
show 18 more comments

Don't know if it can be considered a language feature, but, in C++ almost any compiler error related to templates delivers a fair amount of WTF to many C++ programmers around the world on daily basis :)

link|flag
13  
That's okay, most code related to templates already creates plenty of WTFs around the world. – MadKeithV Jan 4 at 13:31
29  
Oh come now. undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)' Is perfectly readable! – Matt Greer Jan 4 at 20:48
6  
I once had a template-related compiler error that was five lines, the shortest of which was seventeen thousand characters (the classic 'no match for x' error, in a deeply templated program). That's the WTF, not the feature in the first place, templates are wonderful. – Andrew McGregor Jan 5 at 11:26
82  
Even if there's no error, try finding which functions take the longest with your profiler. Oh look, it's std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::vector< std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator>(std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator, std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator, std::allocator<std::pair<int, std::complex> >) – rlbond Jan 5 at 17:24
10  
I think this fits here: Check out STLFilt at bdsoft.com/tools/stlfilt.html to make the output readable. – mxp Jan 6 at 9:58
show 9 more comments

The many name spaces of C:

typedef int i;

void foo()
{
    struct i {i i;} i;
    i: i.i = 3;
    printf( "%i\n", i.i);
}

Or with characters:

typedef char c;

void foo()
{
    struct c {c c;} c;
    c: c.c = 'c';
    printf( "%c\n", c.c);
}
link|flag
11  
+1 Tag identifiers for enums and structs is the most confusing part of C imho. Few people understand why the idiom to typedef a pointer to a structure looks the way it does. – Tadeusz A. Kadłubowski Jan 5 at 9:14
11  
It compiles because every one of those i's has an unambiguous namespace due to context. – Andrew McGregor Jan 6 at 9:31
show 3 more comments

I'm surprised that no one has mentioned Visual Basic's 7 loop constructs.

For i As Integer = 1 to 10 ... Next
While True ... End While
Do While True ... Loop
Do Until True ... Loop
Do ... Loop While True
Do ... Loop Until True
While True ... Wend

Because sticking an ! in front of your conditional is way too complicated!

link|flag
53  
You forgot the best: While ... Wend ???? Is that even a word? – Rune Grimstad Jan 4 at 20:26
35  
They should have made it "While and Whend", since there are some people who do pronounce the word "while" with the voiceless labialised velar approximant. And of course it lines up nicer, and code that lines up is nice. – dreamlax Jan 4 at 21:06
34  
Why are you acting so wheird? – Erik Forbes Jan 4 at 22:13
31  
Wow. I get kinda nostalgic when I think about it. The first time I ever used VB was back as a 9-year old. I'm from sweden, and wasn't very proficient in english back then. Now, there's a swedish word called "vänd" which basically means "turn back" and that is pronounced similarly to "wend". Because of that I thought it made a lot of sense... :) – Emil H Jan 4 at 22:27
39  
! isn't not in VB, it's "Not". Or is it? Yes, not is not !, but Not. – brianary Jan 5 at 0:29
show 18 more comments

Perl has lots of strange quirky features, loved by some, hated by others. There are a few I find particularly WTF-ish:

  • automatic list flattening, i.e., how (1, 2, (3, 4)) is the same as (1, 2, 3, 4);

  • how every operator or function in the language can behave in six different ways depending on the context;

  • the more than a hundred operators and their complex precedence rules. Fortunately Mark Lentczner came up with The Periodic Table of the Operators (Perl 6);

  • the multiple variable namespaces:

    • $var is a scalar named var;
    • $var[41] is the 42nd element of an array named @var;
    • $var{'foo'} is the element with key 'foo' in the hash named %var;

link|flag
6  
I loved the image! – badp Jan 4 at 21:52
162  
You had me at 'Perl' – Shane C. Mason Jan 5 at 2:12
6  
One should point out the operator chart is for Perl 6 while the final point is Perl pre-6. – Richard Jan 5 at 13:30
13  
You're just doing it wrong: (1, 2, [3, 4]). List references are more like the array-type structures that most programmers are used to, I think; just-plain-lists are something many languages don't have, and people are just unsure how they work. They're not really contained, and will mix with each other freely. This is extraordinarily handy when combining them all together though. @listABC = (@listA, @listB, @listC) – fennec Jan 6 at 20:23
3  
@MF it makes it easier to insert some non-list elements in the middle. Happens all the time when constructing command-line or argument lists. (which I'm doing at the moment, and am grateful to Perl for) – JB Jan 7 at 13:10
show 6 more comments

I struggled a bit about this:

1;

In perl, modules need to return something true.

link|flag
5  
That always gave me a queasy feeling, too... – Drew Hall Jan 4 at 8:44
27  
Some modules may return values based on runtime operations. If you always return true, you still don't have to be uncreative about it: returnvalues.useperl.at – Anonymous Jan 4 at 10:06
8  
i respect the perl and its users for their creativity ... – The MYYN Jan 4 at 12:14
4  
If my Perl memory serves me correctly, returning true from a module indicated that the module loaded successfully. Returning a false value meant that something went wrong and would prevent the program from running (if not caught). – Barry Brown Jan 5 at 0:28
15  
Mark Dominus wrote, "I have very rarely used 'Cogito ergo sum'; which as everyone knows is self-evidently true in all possible universes. This ensures maximum portability." – Greg Bacon Jan 27 at 3:50
show 4 more comments

For those who don't know, bc is an "arbitrary precision calculator language", and I use it quite often for quick calculations, particularly when the numbers involved are large ($ is the prompt):

$ bc -lq
12^345
20774466823273785598434446955827049735727869127052322369317059031795\
19704325276892191015329301807037794598378537132233994613616420526484\
93077727371807711237016056649272805971389591721704273857856298577322\
13812114239610682963085721433938547031679267799296826048444696211521\
30457090778409728703018428147734622401526422774317612081074841839507\
864189781700150115308454681772032

bc has been a standard Unix command for a long time.

Now for the "WTF feature". This is from man bc (emphasis mine):

quit: When the quit statement is read, the bc processor is terminated, regardless of where the quit statement is found. For example, "if (0 == 1) quit" will cause bc to terminate.

halt: The halt statement (an extension) is an executed statement that causes the bc processor to quit only when it is executed. For example, "if (0 == 1) halt" will not cause bc to terminate because the halt is not executed.

link|flag
22  
I use Haskell for this stuff. – trinithis Jan 4 at 7:52
5  
Google calculator? – igul222 Jan 5 at 3:51
6  
I've started using Python myself, and google calculator is nice if you're online. But I used to use bc before that, and wanted to write about bc in my post because of the great quotes from the man page. – Alok Jan 5 at 3:57
2  
@Brian, then you will like: echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc (although you might already know this). – Alok Jan 6 at 23:56
show 4 more comments

I would say the whole whitespace thing of Python is my greatest WTF feature. True, you more-or-less get used to it after a while and modern editors make it easy to deal with, but even after mostly full time python development for the past year I'm still convinced it was a Bad Idea. I've read all the reasoning behind it but honestly, it gets in the way of my productivity. Not by much, but it's still a burr under the saddle.

edit: judging by the comments, some people seem to think I don't like to indent my code. That is an incorrect assessment. I've always indented my code no matter what the language and whether I'm forced to or not. What I don't like is that it is the indentation that defines what block a line of code is in. I prefer explicit delimiters for that. Among other reasons, I find explicit delimiters makes it easier to cut and paste code.

For example, if I have a block indented 4 spaces and paste it at the end of a block that is indented 8 spaces, my editor (all editors?) have no idea if the pasted code belongs to the 8-space block or the outer block. OTOH, if I have explicit delimiters it's obvious which block the code belongs to and how it should be (re-)indented -- it does so by intelligently looking for block delimiters.

edit 2: some people who provide comments seem to think this is a feature I hate or that I think makes python a poor language. Again, not true. While I don't like it all that much, that's beside the point. The question is about the strangest language feature, and I think this is strange, by virtue of it being something very, very few (but >0) languages use.

link|flag
48  
if it gets in the way of your productivity then your non-python code can't be very readable... – Tor Valamo Jan 3 at 15:36
21  
What language did you use before Python? How were you able to work with other people and not indent that language? How could anyone put up with non-indented code in any language? Did you work in a room full of geniuses who didn't need visual cues in the source code? – S.Lott Jan 3 at 16:21
43  
+1 Couldn't agree more, if my editor (Emacs) can't indent my code based on something distinct (like braces/begin, end/you name it) automatically, it's seriously silly. Pretty much any refactoring you'd do on a "bigger" function can be a really bad experience. – Dmitry Jan 3 at 16:43
60  
Here's the deal - with any other language, I can highlight a block of code and have it indented properly by any editor. But because whitespace IS by definition the proper indenting, you lose that ability in Python. So it's harder to move code around or refactor things. And for the person who claims the OP is the "first person to claim it was a problem", well I had to maintain some python code for a while and I will now use any language over python for this very reason. – Kendall Helmstetter Gelner Jan 3 at 21:39
29  
I don't mind the whitespace in Python. The WTF is that it's not enforced consistently. You can mix indent levels and tabs, so long as they're consistent with their siblings. So the first indent level can be one space, and the second can be two TABs, and this is not a syntax error. – ieure Jan 4 at 20:51
show 44 more comments

In JavaScript:

2 == [2]

// Even stranger
2 == [[[2]]]

// And down-right nutty
var a = { "abc" : 1 };
a[[[["abc"]]]] === a["abc"]; // this is also true

Luckily the kind folks at stackoverflow.com explained the whole thing to me: http://stackoverflow.com/questions/1724255/why-does-2-2-in-javascript

link|flag
1  
That’s why you should use === instead. – Gumbo Jan 4 at 21:00
9  
This is useful btw, if you have a function that returns a number and you want to return some additional metadata with it, you can return [number] with some additional fields added. Simple code will never know it is not a real number, and other code can get the required metadata. – Andrey Shchekin Jan 5 at 0:28
21  
@Andrey except that if I ever have to maintain code that does what you suggest, I would very soon wish death upon its author. – Breton Jan 5 at 6:45
1  
+1: I've considered myself a knowledgeable js programmer, and I've never known about this :D – trinithis Feb 13 at 17:34
show 3 more comments

I always wondered why the simplest program was:

class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

Whereas it could be:

print "Hello World!"

Maybe this is to frighten computer science students in the first place ...

link|flag
23  
In some languages, "Hello World!" is a valid program. – David Thornley Jan 4 at 20:16
26  
@SoMoS: in most dynamic languages such as Python, Ruby, or Perl print "Hello World!" or some minor variation (e.g. puts instead of print) is a valid and complete program. – Dave Kirby Jan 4 at 20:44
26  
@Loadmaster: the implication was that "all code belongs in a class" or "all code belongs in a function" are unnecessary constraints – Jimmy Jan 5 at 1:22
17  
Just because a language enforces the use of objects, does not mean it is being used for proper object-oriented programming. It is perfectly possible to program procedurally in Java or C#. That's what static methods are for. – jdmichal Jan 5 at 15:28
41  
I love people who think OOP means that everything should be an object. – Tor Valamo Jan 6 at 13:58
show 19 more comments

My biggest most hated feature is any configuration file syntax which includes conditional logic. This sort of thing is rife in the Java world (Ant, Maven etc. you know who you are!).

You just end up programming in a c**p language, with limited debugging and limited editor support.

If you need logic in your configuration the "Pythonic" approach of coding the config in a real language is much much better.

link|flag
18  
Amen........... – erikkallen Jan 4 at 13:47
16  
Tcl re-invented that long before Python was born and Lisp invented it before that. So let's not call it Pythonic, let's call it Emacs-ish. – slebetman Jan 7 at 1:55
26  
Let's just call it Right. – mletterle Jan 7 at 1:57
13  
AMEN. If your configuration or build language is turing complete, you're doing it wrong. I'm looking at you CMake / autotools. – Joseph Garvin Jan 7 at 15:40
11  
This is exactly what Lua was designed for, originally – Cogwheel - Matthew Orlando Jan 18 at 23:00
show 3 more comments

In C

a[i++]= i;

It compiles, but it rarely does what you think it ought to do. An optimization change leads to producing wildly different results. And it runs differently on different platforms.

Yet, the compiler's perfectly happy with it.

link|flag
76  
.. but the language is not. More than one reference to something in an expression that is modified in the expression is undefined behaviour. – Richard Jan 3 at 15:40
17  
"Why would undefined behavior compile and run?". In general because some things which cause UB in C cannot be detected at compile time, and detecting them at run time (or defining the behaviour) would significantly impact performance. In this particular case, I do think it's a bit feeble that compilers generally don't detect the error. It would certainly end a lot of those arguments. But equally I'm not about to submit a patch to gcc to issue a warning. Presumably your compiler's authors are working on other things, which would get pushed back if the C language mandated an error for this code. – Steve Jessop Jan 3 at 17:34
11  
@cschol: "Compilers (or their manufacturers) generally assume you are aware" That's precisely the WTF of C. – S.Lott Jan 3 at 17:41
23  
It's an inevitable consequence of the fact that C permits low-level programming, but CPUs do different things in response to low-level errors. If C had defined all behaviours, then C on x86 would be slow, because it would be attempting to emulate edge-cases from a PDP-7. If you don't like it, you either write in assembly for a particular architecture with fully defined behaviour, or you don't write low-level code. Seems a bit weird though to say in effect, "C's wtf is that it's a portable low-level language". That should not be surprising, since that is its purpose. – Steve Jessop Jan 3 at 17:56
13  
with the the -Wall flag, gcc warns about this warning: operation on 'i' may be undefined – Hasturkun Jan 5 at 11:24
show 17 more comments
1 2 3 4 5 11

Your Answer

 
or
never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.