http://qs321.pair.com?node_id=203269


in reply to RFC: Shell::DWIM

This is tangentially related to a meditation japhy posted last year about fixing system, and index and rindex as well. Read about it at japhygesis.

My own preference tends towards the solutions presented in that thread. There's nothing wrong with what you propose, except that I have to remember a lot more details in order to use it, hence more mental effort is required. In light of this, I find it acceptable to redefine system to Do The Right Thing if it makes the code simpler.

<update>To clarify, Shell::DWIM::run is more to type than system and even at a simpler level 'run' ne 'system'. I have to remember not to try doing a Shell::DWIM::system. And in two months time I'll wonder whether it is run or Run and will have to consult the documentation to check if I remembered correctly. Maybe I'm not a significant data point in the debate after all: I'm comfortable with the concept that system returns the OS error code, and 0 is considered success (which means that in a conditional the test for failure is reversed), and that you get the details of the child though $?.</update>

This does, of course, have to be traded off against the possibility of subsequent people looking at the source and not immediately grasping the fact that system's return code has been reversed.

For instance, if you only have one system call it's probably not worth it. But if you're replacing a humungous shell script with dozens of systems, there's a fair chance that adopting this approach will make the code clearer to understand, because it makes them look much more like subroutines and thus you move away from the shellish mindset and into the realm of procedural programming.


I just thought of something else: I don't like modules that export variables. Sooner or later you'll get someone in serious reality denial who is going to say:

sub my_job { Shell::DWIM::run( '/dev/null', @_ ); $Shell::DWIM::RUN_ERROR = 0; # Error? There is no error in my code return $Shell::DWIM::RUN_ERROR; }

To protect yourself, especially as these are read-only values, you want to do something like:

sub RUN_ERROR { $RUN_ERROR }

Mind you, people can do that with $!. So if you went ahead and did this, you would offer protection that can't be had by normal means. That in itself would be justification enough for this module.


print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'