20 March 2013

how simple things can go awfully wrong

You know programming languages? At least one or two?

A two-liner, without any regular expression, should not be a too-great adventure...

Try the following in your favorite language:

i = 1
i += ++i + ++i

A simple assignment to an integer variable, some forms of add-operators.

They're evil - believe me. Things go wrong from here:

Let's analyse the expression in a functional way:

  • With i set to 1, the first ++i should yield 2.
  • Calculate the two of them one-after-the other, the second one yields 3.
  • Calculate the two of them in parallel, both yield 2.

So - the result should be something between 5 and 6.

Let's try Ruby first:

ruby-fails

Slightly off any sensible calculation. Consider it "failed".

Move on with Java:

java funny expression

Believe me, C# and JavaScript and some other JVM languages come to the same conclusion.

But we're not finished here. Fire up your command line and type:

awk 'BEGIN {i=1; i+= ++i + ++i; printf i}'

Puuh - yields 8. Eight. Seems a bit off for me, but awk might have reasons.

We'll check that with php in a second:

 

NewImage

 

Eight again. So many commercial websites are build with php - and they all calculate like that? re-consider your e-commerce behaviour...

Now, if you happen to have one of those wonderful GNU-C compilers installed - try out the objective-C variant of this expression: You will see eight again. Two more than with Java.

 

Finally, the mother of all programming languages, the common ground of all platforms, the C programming language:

#include <stdio.h>
int main(int argc, const char* argv[]) {
int i = 1;
i += ++i + ++i;
printf("i+= ++i + ++i liefert %i\n", i);
return 0;
}
==> 9

I have to declare it the winner of this informal competition. At least numerically the winner: Nine. 9. Three times three.

Three times what Ruby calculates. 30% more than Java and C#. Btw, compiled with the same GNU compiler that found 8 to be the answer for Objective-C. 

 If you check that with Perl, fine: Nine again:

#!/usr/bin/perl
$i=1;
$i += ++$i + ++$i;
print "i = ".$i."\n";
print "\n\n";
==> 9

I personally stopped laughing here: If we stumble upon two-liners, what about real programs, with memory, sync/async, concurrency and UI issues? With changing requirements?

 

Eventually, thinking (!) about your software might help, so instead of "test driven" or "behavior driven" or "nerd driven", what about "thought driven development" (as Rich Hickey pointed out in his famous speech "Hammmock Driven Development"

 

As a sidenote: Cobol outputs 6. I did not find any solution less than 3, nor one greater than 9.

PS: Thanx to Franz Antesberger for this nice riddle!

8 comments:

Steven Kelly said...

8 sounds more plausible to me than most answers != 6.
First do the RHS: first ++i is 2, second ++i is 3, add them and you get 5.
Then do the +=: i is currently 3, plus the RHS 5, so set i to 8.

Schnickschnack said...

Whoever writes such code deverses whatever answer they get.

Vincent said...

There is no pre-increment in Ruby, instead ++i is interpreted as two unary '+'-operators (pretty useless). Therefore ++i + ++i is the same as i + i in Ruby.

Cybso said...
This comment has been removed by the author.
Cybso said...

gcc does both increments on the same register, resulting in i += 3 + 3.

Eberhard Wolff said...

Your code should not rely on such behavior of a language. I think a problem are certifications that actually teach such corner cases and might lead people to believe such code is OK.

Cybso said...

Btw, compiled with clang (llvm) this results in 8.

Cybso said...

Btw, compiled with clang (llvm) this results in 8.