http://qs1969.pair.com?node_id=125918

deprecated has asked for the wisdom of the Perl Monks concerning the following question:

Scenario:

I have 36 directories. Inside those 36 directories are some ten thousand additional directories. Inside each of those sub directories are a set of files. These files are regularly named. They reflect information stored elsewhere on the disk. It is my task to take the data in the sub directories and reflect them in our database.

I've been doing this with a copy of a script that the original planner of this system had used to convert the data to html.

The reason I'm looking to change it is a) I didnt write it, and its difficult to work with and b) its a 300-line-long if/elsif/else "loop." In other words, its basically three opendirs, with the last one goes over every file, compares it to a regular expression, and then modifies a corresponding variable. that variable is then stored in the database.

an example:

/data/sprocket_logs/spacely.200 /data/sprocket_logs/cogswell.100 /data/cog_logs/cogswell.1000 /data/cog_logs/astro.1
we could interpret this to mean that spacely has 200 sprockets, and that cogswell has 100 sprockets and 1000 cogs, while astro has 1 cog. However, this is not the only kind of information stored in these directories. for example we might see:
/data/cog_logs/maimed_a_robot
indicating that at one point a cog was responsible for a robot maiming. now I know what all these files are going to look like, and have a regular expression for the particular parsing of each of them. however, this if/elsif/else construct is irritating the heck out of me. It is not the right way to do this.

However, when i started coming up with a solution that was more comprehensive, I came up with this:

my %dispatcher => ( \$quux => [ sub { return 0 unless $_[0] =~ ${$_[1]}; ${$_[3]} =~ s/${$_[1]}/${$_[2]}/; return $_[3]; }, qr{bar}, qq{foo}, ], ); $dispatcher{$key} -> [0] -> ($file, $dispatcher{$key} -> [0] -> [1], $dispatcher{$key} -> [0 +] -> [1]);
What this basically does is, (and note the syntax may be off, it's not yet gone past perl -c) is there is a hash with the variables i want to change. each variable has a corresponding listref value which contains the sub that actually changes its value, and the pattern it needs to match for the change to occur, and what to change it to. so, i think its actually even a little elegant. however, it takes up more space and is less maintainable than the "dreaded" if-elsif-else construct.

There has to be a better way than three hundred lines of if statements.

What have you all done when faced with this situation?

thanks,
brother dep.

--
Laziness, Impatience, Hubris, and Generosity.