The Hypothetical Comma Challenge

The challenge: submit two syntactically valid programs of any length in any programming language, differing only by a comma, that do something interestingly different from each other. Bonus points if they're syntactically valid in different programming languages. The contest has now finished, with Alex and Totherme as the winners.

Alex Comer - C

/* ==========================================
   Stick this in your C compiler and smoke it
   ========================================== */

#include <stdio.h>

#define WITH_COMMA

int main(int argc, char *argv[])
{
    long int c[4] = { 1701869928, 7894355, 1701869928, 7892818 };

#ifdef WITH_COMMA
    printf( (char *)&c[-(1,-1)<<1] );
#else
    printf( (char *)&c[-(1-1)<<1] );
#endif

    return 0;
}

/* NB:
   This works just peachy in my Windoze, but may not work
   on all platforms (how long is long and does your big end
   go in the front or the back?)  The comma bit is pretty
   simple tho, and that *is* cross-platform.

   Ciao,

      /-\ |_ [- ><

*/
It seems to work fine in Linux as well.

Me - Perl and vi

The use-a-language-that's-already-stupidly-terse approach. NB I am obviously not eligible: I can buy myself a drink any time.
#!/usr/bin/perl -w
# matches lines with three or more characters
while (<>) {
	print if /^.{3,}$/;	
}

#!/usr/bin/perl -w
# matches lines with exactly three characters
while (<>) {
	print if /^.{3}$/;	
}
Add the following lines to .vimrc or save to comma.vim and type :source comma.vim in vim.
"in vi, 'fx' means 'move to next occurrence of x'
"',' means 'repeat last f command in reverse direction'
map <F1> f,,
map <F2> f,
" F1 moves to the first comma before or under the cursor,
" F2 moves to the first comma after the cursor.

Gareth Smith - CSP and Prolog

Actually, the CSP one doesn't count, because it uses apostrophes instead of commas, but I've included it here anyway for interest.

It's easier with apostrophes in my current frame of mind...

-- CSP Comment
-- Prog One:
channel: event, event2
F = event -> F
F' = event2 -> STOP

-- Prog 2:
channel: event, event2
F = event -> F'
F' = event2 -> STOP

In prog1, F (the process we're concerned with) loops forever, always performing event. In prog2 it halts gracefully with event2.

If we want to make a more theoretical difference, we can hide event:

-- Prog One:
channel: event, event2
F = event -> F \ {event}
F' = event2 -> STOP

-- Prog 2:
channel: event, event2
F = event -> F' \ {event}
F' = event2 -> STOP

In which case, F in prog 1 livelocks - always looking internally busy but never doing anything the outside world can see. This is an arse, because you can wait an eternity for these things to come out of the loop.

I suppose you could make it more drastic...

-- Prog One:
channel: event, event2
F = (event |-| event2) -> F
F' = event -> F'

LOOKATTHIS = F || F

-- Prog 2:
channel: event, event2
F = (event |-| event2) -> F
F' = event -> F'

LOOKATTHIS = F || F'

Prog2 will perform an infinite sequence of randomly chosen events and event2s. Prog1 will sometimes perform a random sequence of 0 or more events and event2s and then deadlock. Or not.

Deadlock is when 2 processes are waiting for each other to do something. Neither of them will do the thing the other is waiting for, since it's waiting. See the dining philosopher problem etc.

If you hide event you add the possiblity that either process will livelock, but this is neither here nor there, since both processes can do that.

At the end of the day, all this stuff is the same thing, but seen from different angles.

In prolog we can use commas....

How bout:

% Prolog comment
% Prog 1
wumpus(X,Y):-          % Is there a wumpus in this square?
  state(wumpus, [X,Y]).

wumpus(X):-            % Is there a wumpus in this row?
  state(wumpus, [X,_]).

isSquareSafe(X,Y):-    % Is this square safe?
  not(wumpus(X,Y)).

% Prog 2
wumpus(X,Y):-          % Is there a wumpus in this square?
  state(wumpus, [X,Y]).

wumpus(X):-            % Is there a wumpus in this row?
  state(wumpus, [X,_]).

isSquareSafe(X,Y):-    % Is this square safe?
  not(wumpus(XY)).

We assume that someone has been updating the state predicate with the latest wumpus movement intel. This is a small part of the decision making bit of an AI. The wumpus movement intel comes from the senses which are left as an exercise for the reader.

In Prog1 the predicate isSquareSafe(X,Y) is true iff there is no wumpus in [X,Y]. In Prog2, isSquareSafe(XY) is true iff there is no square in the known world that contains a wumpus. This might be seen to result in an overly cautious agent.

This makes use of 3 language features:

  1. Different predicates with the same name and different numbers of params. Always dangerous, and yet none of us want to give them up.
  2. Unification of unknown parameters. This is what makes prolog great, and unfortunately is a bit like perl magic variables. If prolog sees a name it hasn't seen before, it assumes it's an unknown and tries to work it out later.
  3. Not in prolog is not the same as logical not. Not is only guarenteed to give logical not answers if all the variables going into it are isntantiated. We made up a variable "XY", which prolog tried to unify inside the not. The result is that it looks for any row with a wumpus in it. If it finds one, the not immediately dubs the predicate as false.