robartes is right.
(Note: I'll be using the words 'compile-time' and 'run-time', even though there
is no clear distinction in Perl which is when.)
The first definition is happening at compile-time, the second is at run-time. One
might expect that in print foo(), a subroutine is called, and
that that happens at run-time, thus using the new definition of foo().
But there is no subroutine call. Perl tries to be smart, and optimizes the code.
The foo() has become a constant, the actual print that does happen
is just print 2, as dada points out.
podmaster was able to redefine the function effectively, because BEGIN
blocks are executed as soon as possible (i.e. immediately), and redefinition
takes place before run-time and before the foo() "call" is encountered. Other compile-time tricks would allow redefinition
too, like having the code in a .pm file and using use.
You get the expected 3 if you force Perl to actually call the subroutine
. You can do that by using the & sigil. This disables prototype
checking and inlining (probably because inlining depends on the prototype).
perl -le'sub foo(){2};*::foo=sub(){3};print &foo()'
Other ways of avoiding Perl to inline foo() are:
print *foo{CODE}();
print eval 'foo()';
(I think I found a bug in my B::Deparse. perl -e'sub foo(){2}'
doesn't even display the definition of foo, while dada's Deparse does display
inlined subroutines. It's not as if the sub is completely gone:
perl -le'sub foo(){2} print *foo{CODE}()' does work as expected. Perl 5.8.0 on
linux x86. Please confirm.)