Re: mini-quiz

Joshua Kronengold <[email protected]> Wed, 20 Jun 2007 10:09:04 -0400
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <[email protected]>
On Wed, 20 Jun 2007 5:15 am, Mike South wrote:
> On 6/19/07, Joshua Kronengold <[email protected]> wrote:
>> On Tue, 19 Jun 2007 12:50am, Ron Isaacson wrote:
>>>  Joshua Kronengold wrote:
>>>>   >>  my $country = map +(/^(?:|gbr)$/ ? '' : uc),$card->country;
> The part where you are using map, which returns an array, and you are
> getting a scalar back which will always be 1? :)  Of course I'm partly
> saying that just to be funny, but there are a lot of things that have
> to be right in your idiom:

It's true.  And this is an interesting conundrum -- I chose map because 
it's the only really appropriate "filter" that avoids redundantly 
referring to the same variable more than once and avoids explicitly 
making a temp variable or reusing $country for that purpose.  But 
really, it's not ideal for the reasons you list.  If there were a scalar 
map (ie "filter", that would work better, but there isn't one.

I think this is a "fixed in six" issue, but then, isn't everything?

> ^, $ anchors on the regex because you're really specifying values for
> the whole string

Yes.  That said, this is something perl programmers need to learn to get 
right by habit -- all too often, I've run into the opposite issue with 
insufficiently bound regexps.

> parens on the regex so that you don't get alternation between the ^
> zero-width assertion and gbr$

Same as the above.

> + in front of the () after the map so it doesn't look like map()
Actually, to be fair, the parens are unnecessary here -- since the fancy 
comma binds more loosely than the alternation.

The reason I keep it in here is that it's generally useful for clarity 
-- and because it's -very- important that people use parentheses when 
using alternations that returns lists rather than scalars.

> , after the () after the map since it's the map EXPR, ARRAY form
>
> (Everything else aside, I would use the "map {} " form--is there a
> reason not to?  All I see is two extra characters to type, but I'm
> interested to know if there's a good reason.)

This is an interesting question.  Your objections to expr map are 
-largely- the general unfamiliarity with that form, but in fact I've 
tended over the last 4-5 years to gravitate to using expression map over 
block map (except when block map is actually called for, because a map 
involves more than one phrase or because it needs a lexical scope) for a 
couple of reasons:

1. Efficiency.  It's a stupid reason, but nevertheless, expr map is 
faster than block map, which can matter in some applications.

2. Clarity.  Once you get over the fact that most perl programmers have 
never seen an expr map in their life, the fact that there are a lot of 
limitations to what the enclosing expression can do (has no scope, 
cannot contain more than an rvalue, no semicolons) is very useful to the 
reader as bounding the purpose of the expression, as is the connotation 
that the expression is unlikely to produce side effects (not that side 
effects aren't generally a bad idea in maps, because they are).  This is 
in some ways similar to why it's better to use undefs, not positive 
values, for an assertion hash -- if you can only use exists() to test 
for truth, you're only going to -see- exists() used for that purpose, 
and much less likely to see obsucre bugs showing up because people used 
a mix of that and naked truth tests.

And, of course, there are outside the scope of this, maps where using a 
naked expression provides added clarity, like when you're mapping to a 
list.  At least, I think the first of these is clearer:

my %h = map +($_ => undef) => @keys;

vs

my %h = map { $_ => undef } @keys;

(even if you add the parentheses back in)

(questions of whether the above is better/worse than "my %h; @h{@keys} = 
()" aside.)

> like "best idiom" is
> problematic, as idioms tend to localize.

Yup.

Depending on your idiomatic familiarity, a new idiom might be 
immediately obvious or beyond the pale -- especially when (as in my 
example) it actually embeds other potentially unfamiliar idioms.