This post described the littlest little language I’ve ever implemented, which would expand ranges like ‘A-Z’ or ‘0-9′ in a string. Following some suggestions by BKB in the comments, here’s a bunch of stylistic alternatives.
My first one was kind of over-cautious. The range-expansion logic is separated out into its own function, which handles dumb stuff like invalid ranges, and also documents itself. Although ‘expand_range’ would be a better name for that.
s/(.)-(.)/expand_pair($1, $2)/eg
BKB got it into one line. I wouldn’t do it like this, because on returning to this code, I’d have to spend too much time remembering what it was supposed to be doing:
s/(.)-(.)/join('', map { chr($_) } ord($1)..ord($2))/eg
BKB’s first version was this, which he corrected:
s/(.)-(.)/join('', $1..$2)/eg
I tried it, just to see what would happen, and found that the ‘..’ operator will not just return (1, 2, 3, 4, 5) from 1..5: it will also return (‘a’, ‘b’, ‘c’, ‘d’, ‘e’) from ‘a’..’b’ or (‘A’, ‘B’, ‘C’, ‘D’, ‘E’) from ‘A’..’Z’ In other words, it works for most useful cases.
In one way, I like this version the most: it’s a highly readable one-liner which works. In another way, I like it the least, because if you think about it for a little bit, it seems like it might be broken.
I then tried this, just to see what would happen:
s/(.)-(.)/$1..$2/eg;
It turns every range into ‘1E0′, but I haven’t yet figured out why. Sometimes you just want to see how much tomfoolery Perl will put up with.