Question 2: How to reload a module without having to use an eval (like eval "My::Run()")
Reloading a module will always end in a string eval, like loading a module does. Remember or read the docs:
- use Some::Module ...; is exactly equivalent to BEGIN { require Some::Module; Some::Module->import(...); }
- require Some::Module; behaves like a 50 line wrapper around do "$prefix/Some/Module.pm" searching for Some/Module.pm along @INC and updating %INC.
- do "$prefix/Some/Module.pm" behaves much like $text=readFile("$prefix/Some/Module.pm"); eval $text;, searching @INC and setting %INC (and $@ and perhaps $! on error).
So, in EVERY use and require, a string eval is hidden. And that string eval will happen unless the requested module has already been loaded. If you load or reload a module at runtime, there will always be a string eval. So a simple eval "require Some::Module" does not hurt much. Of course, you can manually search for the module and do a require "$prefix/Some/Module.pm", but it will still hide a string eval.
Another way to reload updated modules is to just re-execute your script. Store $^X, $0 and @ARGV at startup, then when you feel the need to reload modules, run something like exec { $^X } $^X,$0,@ARGV; die "Re-exec failed: $!";. This will completely restart your script, loading all modules again. Of course, there are limitations:
- Your operating system may not support exec, in that case, perl may provide a rough emulation (Windows - see exec in perlport).
- If your STDIN comes from something like a socket or a terminal, the data you have already processed is lost.
- Some operating systems do not flush output file handles on exec, so some output may be lost. Again see exec in perlport.
- If your script generates some "startup noise" (e.g. write a header to STDOUT), that will probably be repeated unless you find a way to detect a re-exec. Adding a flag to %ENV or the stored copy of @ARGV might be an idea.
- All variables are lost. You must be able to regenerate the state of your program from the available input at the time of exec. If you can't, saving essential state information to a file (JSON, Storable) before exec and reading it back after exec might be an idea.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)