- Actually you can redefine subroutine by using eval "sub func {'...'}"
That would create a new function at runtime, but it wouldn't follow the rules of dynamic scoping (see MOPT-03 for details).
As you've used it, the eval() just binds a new function to the name 'func'. To be dynamic, the new version of func() would have to be restricted to the evaluation context of the function that defined it:
$VAR = "old VAR";
sub func {return ("old func()")}
sub show {printf "VAR='%s', func()='%s'\n", $VAR, func()}
sub redefine {
eval 'sub func {return ("new func()")}';
local ($VAR) = "new VAR";
show();
}
show();
redefine();
show();
returns:
VAR='old VAR', func()='old func()'
VAR='new VAR', func()='new func()'
VAR='old VAR', func()='new func()'
which shows the difference between redefining a globally-scoped function and re-binding a dynamically-scoped variable.
- and better yet is just to use anonymous subroutines and use ordinary variables to switch between different ones:
Yes, that would work:
$VAR = "old VAR";
$FUNC = sub {return ("old func()")};
sub show {printf "VAR='%s', func()='%s'\n", $VAR, &$FUNC()}
sub redefine {
local ($FUNC) = sub {return ("new func()")};
local ($VAR) = "new VAR";
show();
}
show();
redefine();
show();
returns:
VAR='old VAR', func()='old func()'
VAR='new VAR', func()='new func()'
VAR='old VAR', func()='old func()'
which does the right thing. But to get the effect of a dynamically-scoped function, you have to use a dynamically scoped (aka: local) variable, and I did say that in the original article.
HOWEVER.. check out the next reply to see how I was, in fact, wrong.
|