There are hundreds of situations where the exact same logic can be written in a number of ways. This is TMTOWTDI, and one of the foundations of Perl. However, there're usually worse ways and better ways. This is to discuss some of the better ways, when it comes to maintainability. Now, some of these may be worse, performance-wise. However, I'm going to say that, when it comes to a normal application, "fast enough" is a very important concept. If you need more speed, add RAM. If you need more speed, add more CPU. If you need even more speed, then optimize your code. Your time coding is the most expensive part of an application. Remember that. Now, onto some examples.
Let's say that you have a $typeNum, which is one of 1, 2, or 3. There's also a $typeName for each $typeNum, and you need to be able to convert between the two. We have a function that does it. But, what should the function do?
That's the most obvious and brute force method. And, I must say, it works perfectly fine in this instance. However, what if there are 26 choices? The canonical answer is to create a hash or array, with keys of $typeNum and values of $typeName. And, that works perfectly fine. But, what if all your values map perfectly well like this?sub getTypeName { my $typeNum = shift; if ($typeNum == 1) { return "A NAME"; } elsif ($typeNum == 2) { return "B NAME"; } elsif ($typeNum == 3) { return "C NAME"; } else { die "$typeNum not valid\n"; } }
Now, what if you have a string you want to break up. If it's nicely delimited, you can use split very nicely. But, what if it's positional? The obvious answer is to use substr a number of times, sorta like thissub getTypeName { my $typeNum = shift; die "$typeNum not valid\n" unless 1 <= $typeNum && $typeNum <= 3; my $typeName = ('A' .. 'C')[$typeNum - 1] . " NAME"; return $typeName; }
Again, this doesn't scale very well beyond, say, three items. Even then, it's ugly. So, the first thing most people do is turn to unpack. That would look something likemy $first = substr $line, 0, 2; my $second = substr $line, 2, 4; my $third = substr $line 10, 4;
That $junk in there isn't very aesthetically pleasing. So, how about we do something likemy ($first, $second, $junk, $third) = unpack "A2A4A4A4", $line;
This is using the concepts of lists and slices. unpack returns a list. Instead of assigning that list immediately, you can index into that list, either as a straight access or a slice.my ($first, $second, $third) = (unpack "A2A4A4A4", $line)[0,1,3]; # Or, you could do ... my ($first, $second, $third) = ($line =~ /(.{2})(.{4})(.{4})(.{4})/)[0 +,1,3];
Now, I'm still very unhappy about the fact that we have three variables. We could easily assign it to a list and call it @data, but I don't like having to use numeric indices. I'd much rather use a hash. Maybe something like
Now, that's more like it!my @colNames = qw(first second third); my %hash; @hash{@colNames) = (unpack "A2A4A4A4", $line)[0,1,3];
Update: davorg's comment about the template definitions in unpack is right on the money. I'm not very familiar with it, primarily because I never use pack or unpack for parsing fixed-length records. I will usually do a split //, $line and work with the resultant array, either with splice, shift, or foreach. The idea was to demonstrate that slicing is a useful direction to go in many cases.
------
We are the carpenters and bricklayers of the Information Age.
Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Maintainable code is the best code Part II
by runrig (Abbot) on Oct 02, 2001 at 23:55 UTC | |
$skin{cat}++
by boo_radley (Parson) on Oct 03, 2001 at 00:35 UTC | |
Re: Maintainable code is the best code Part II
by davorg (Chancellor) on Oct 03, 2001 at 12:41 UTC | |
Re: Maintainable code is the best code Part II
by AidanLee (Chaplain) on Oct 03, 2001 at 16:16 UTC | |
Re (tilly) 1: Maintainable code is the best code Part II
by tilly (Archbishop) on Oct 04, 2001 at 16:43 UTC | |
by dragonchild (Archbishop) on Oct 04, 2001 at 18:43 UTC |