[SPOILER] Re: New Quiz: "What does this code do?" (1-December-2006)

Shlomi Fish <shlomif-ik1l9ssToec+JF/[email protected]> Thu, 14 Dec 2006 05:13:03 +0200
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <[email protected]>
Hello to everybody,

it's been almost two weeks since this quiz was posted and I neglected to post 
a spoiler as I've been unfortunately distracted by other things. Thanks to 
everyone who submitted me a solution for this problem.

Now let's go over the code.

On Friday 01 December 2006 16:35, Shlomi Fish wrote:
> Hi all!
>
> Well, it's been a while since we had a quiz so here's another what does
> this code do quiz:
>
> {{{{{{
>     my (@list) =
>     (
>         grep { $cgi->param("$prefix$_") }
>         map { /^${prefix}(\d+)$/ ? ($1) : () }
>         $cgi->param()
>     );
> }}}}}}

$cgi->param() in list context returns a list of all CGI parameter "NAME"s. The 
map part matches against a regex which matches a prefix string followed by 
digits. If a NAME matches the retgex the digit part is extracted, and if 
doesn't, it is skipped.

The grep makes sure the $cgi->param() of the original NAME (with the prefix 
back on) is true.

This was used in an HTML form where there was a checkbox with a certain prefix 
for every ID:

<<<<<

<input type="checkbox" name="toggle_1" />
<input type="checkbox" name="toggle_2" />
<input type="checkbox" name="toggle_3" />
.
.
.
>>>>>

And this snippet was used to extract the IDs that were checked.

Now for some interesting input from the solvers:

1. Ronald J. Kimball suggested using the following snippet instead:

<<<<<<<<
my(@list) =
(
    map { /^${prefix}(\d+)$/ && $cgi->param($_) ? $1 : () }
        $cgi->param()
);
>>>>>>>>

When I said that $1 may be destroyed by the param method call, he noted that 
$1 was locally scoped, which indeed seems to be the case. So my code should 
be written like that instead.

2. Peter Haworth correctly detected the use that I made of the code and 
suggested using a checkbox group instead:

<<<
<input type="checkbox" name="toggle" value="1" />
<input type="checkbox" name="toggle" value="2" />
<input type="checkbox" name="toggle" value="3" />

Etc.
>>>

And then just say <<< my @list = $cgi->param("toggle"); >>>. 

He also suggested the following alternative code:

<<<<<<<<<
my @list=grep /\A$prefix\d+\z/ && $cgi->param($_),$cgi->param;
s/\A$prefix// for @list;
>>>>>>>>>

3. Some people suggested the following wrong codes. Can you detect why they 
are wrong?

<<<<
my @list
 = grep { /^$prefix(\d+)$/ && $cgi->param("$prefix$1") }
 $cgi->param();
>>>>

<<<<
my @list =  map { $cgi->param( $_ ) }
             grep { /^$prefix(?:\d+)?$/ }
               $cgi->param();
>>>>

<<<<
my @list = grep { /^${prefix}(\d+)$/ && $cgi->param($_) } $cgi->param();
>>>>

4. Many people wrongly believed that @list returns the NAMES along with the 
prefix instead of just the IDs.
--------------

Well, this was fun quiz, and I enjoyed reading your answers. Those who sent a 
reply to me in private may be interested in forwarding it to the list.

If anyone has an idea for a quiz, he or she should feel free to send it to the 
list.

Regards,

	Shlomi Fish

---------------------------------------------------------------------
Shlomi Fish      shlomif-ik1l9ssToec+JF/[email protected]
Homepage:        http://www.shlomifish.org/

Chuck Norris wrote a complete Perl 6 implementation in a day but then
destroyed all evidence with his bare hands, so no one will know his secrets.