#!/usr/bin/perl
#####################
#
# A first (and not very satisfactory) look 
# at the behavior of Perl's increment operator,
# in particular the weird behavior of (++$m + $m++).
#
# See ./quantum_weirdness.txt
#
# Jim Mahoney 
# Marlboro College
# mahoney@marlboro.edu
#
# Copywright 2004.  This program is free software; you may 
# redistribute it and/or modify it under the same terms as Perl itself.
#########################

use strict;
use warnings;
my $m;

print "\n A look at the increment operators and their side effects.\n\n";

my @perlcode = (   ' $m=20; $m = $m++;        ',
                   ' $m=20; $m = ++$m;        ',
                   ' $m=20; $m = $m++ + ++$m; ',
                   ' $m=20; $m = ++$m + $m++; ',
                   ' $m=20; $m = $m++ + $m++; ',
                   ' $m=20; $m = ++$m + ++$m; ',
               );

my @with_post_and_pre = my @with_noop = my @with_look = @perlcode;
s/(\S\S)\+\+/pre($1)/g, s/\+\+(\S\S)/post($1)/g for @with_post_and_pre;
s/(\S\S\+\+|\+\+\S\S)/noop($1)/g                for @with_noop;
s/(\S\S\+\+|\+\+\S\S)/look($1)/g                for @with_look;

foreach my $line (@perlcode, @with_look, @with_post_and_pre, @with_noop){
  print("After {$line} \n");
  eval $line;
  print("m is $m in " . \$m . ".\n\n");
}

print " - - - - - - - - - - - - - - - - - \n\n";

while (@perlcode){
  my $perl      = shift @perlcode;
  my $m_perl    = eval $perl;
  my $watched   = shift @with_noop;
  my $m_watched = eval $watched;
  if ($m_perl != $m_watched){
    print " Quantum weirdness : \n";
    print "   { $perl } gives m = $m_perl. \n";
    print "   { $watched } gives m = $m_watched. \n";
    print "\n";
  }
}

exit;

# --- subroutines ----

# Trying to emulate the pre-increment operator.
sub pre {
  $_[0] = $_[0] + 1;   # increment 
  return $_[0];        # return incremented value
}

# Trying to emulate the post-increment operator.
sub post {
  my $tmp = $_[0];     # make a copy of value
  $_[0] = $_[0] + 1;   # increment 
  return $tmp;         # return value before increment
}


# Print out some info about a value and return it.
sub look {
  print "    ...look() gets '$_[0]' in " . \$_[0] . " when m = $m in " .\$m . ".\n";
  return $_[0];
}

# Do nothing; just return the value passed in.
sub noop {
  return shift;
}

__END__
==================================================================


 The $m++ and ++$m behavior can almost be 
 emulated with post($m) and pre($m), but not quite.

 I've run this on v5.8.0 on i386-linux and 5.8.1-RC3 on darwin
 and seen the same answers on both.

=========== output ==================================================

$ ./increment_detail.pl 

 A look at the increment operators and their side effects.

After { $m=20; $m = $m++;        } 
m is 20 in SCALAR(0x805fb64).

After { $m=20; $m = ++$m;        } 
m is 21 in SCALAR(0x805fb64).

After { $m=20; $m = $m++ + ++$m; } 
m is 42 in SCALAR(0x805fb64).

After { $m=20; $m = ++$m + $m++; } 
m is 43 in SCALAR(0x805fb64).

After { $m=20; $m = $m++ + $m++; } 
m is 41 in SCALAR(0x805fb64).

After { $m=20; $m = ++$m + ++$m; } 
m is 44 in SCALAR(0x805fb64).

After { $m=20; $m = look($m++);        } 
    ...look() gets '20' in SCALAR(0x8094f6c) when m = 21 in SCALAR(0x805fb64).
m is 20 in SCALAR(0x805fb64).

After { $m=20; $m = look(++$m);        } 
    ...look() gets '21' in SCALAR(0x805fb64) when m = 21 in SCALAR(0x805fb64).
m is 21 in SCALAR(0x805fb64).

After { $m=20; $m = look($m++) + look(++$m); } 
    ...look() gets '20' in SCALAR(0x809508c) when m = 21 in SCALAR(0x805fb64).
    ...look() gets '22' in SCALAR(0x805fb64) when m = 22 in SCALAR(0x805fb64).
m is 42 in SCALAR(0x805fb64).

After { $m=20; $m = look(++$m) + look($m++); } 
    ...look() gets '21' in SCALAR(0x805fb64) when m = 21 in SCALAR(0x805fb64).
    ...look() gets '21' in SCALAR(0x8094fb4) when m = 22 in SCALAR(0x805fb64).
m is 42 in SCALAR(0x805fb64).

After { $m=20; $m = look($m++) + look($m++); } 
    ...look() gets '20' in SCALAR(0x8094fcc) when m = 21 in SCALAR(0x805fb64).
    ...look() gets '21' in SCALAR(0x8094fcc) when m = 22 in SCALAR(0x805fb64).
m is 41 in SCALAR(0x805fb64).

After { $m=20; $m = look(++$m) + look(++$m); } 
    ...look() gets '21' in SCALAR(0x805fb64) when m = 21 in SCALAR(0x805fb64).
    ...look() gets '22' in SCALAR(0x805fb64) when m = 22 in SCALAR(0x805fb64).
m is 43 in SCALAR(0x805fb64).

After { $m=20; $m = pre($m);        } 
m is 21 in SCALAR(0x805fb64).

After { $m=20; $m = post($m);        } 
m is 20 in SCALAR(0x805fb64).

After { $m=20; $m = pre($m) + post($m); } 
m is 42 in SCALAR(0x805fb64).

After { $m=20; $m = post($m) + pre($m); } 
m is 42 in SCALAR(0x805fb64).

After { $m=20; $m = pre($m) + pre($m); } 
m is 43 in SCALAR(0x805fb64).

After { $m=20; $m = post($m) + post($m); } 
m is 41 in SCALAR(0x805fb64).

After { $m=20; $m = noop($m++);        } 
m is 20 in SCALAR(0x805fb64).

After { $m=20; $m = noop(++$m);        } 
m is 21 in SCALAR(0x805fb64).

After { $m=20; $m = noop($m++) + noop(++$m); } 
m is 42 in SCALAR(0x805fb64).

After { $m=20; $m = noop(++$m) + noop($m++); } 
m is 42 in SCALAR(0x805fb64).

After { $m=20; $m = noop($m++) + noop($m++); } 
m is 41 in SCALAR(0x805fb64).

After { $m=20; $m = noop(++$m) + noop(++$m); } 
m is 43 in SCALAR(0x805fb64).

 - - - - - - - - - - - - - - - - - 

 Quantum weirdness : 
   {  $m=20; $m = ++$m + $m++;  } gives m = 43. 
   {  $m=20; $m = noop(++$m) + noop($m++);  } gives m = 42. 

 Quantum weirdness : 
   {  $m=20; $m = ++$m + ++$m;  } gives m = 44. 
   {  $m=20; $m = noop(++$m) + noop(++$m);  } gives m = 43. 

syntax highlighted by Perl::Tidy 20060719