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

I understand some of the below but need explanation of what the undef and the mapping is doing?? I know it is saying dont use the fields in the qw part but not sure how it works??
use strict; foreach my $field (param) { #cover multivalued fields like checkboxes? Is this correct? foreach my $value (param($field)) { #not sure what the mapping and undef are doing with the field var +iable? next if exists { map {$_ => undef } qw(city state country) } -> { $field }; #process non blank thedata variable if($value !~ /^\s*$/) { my $thedata .= "$field\:\t$value<br />"; } } }

Replies are listed 'Best First'.
Re: Explanation of mapping and undef
by broquaint (Abbot) on Jun 08, 2004 at 11:09 UTC
    next if exists { map {$_ => undef } qw(city state country) } -> { $field };
    This is creating a temporary anonymous hash where the keys are the values in the qw// and then checking for the existence of $field in that hash. For a breakdown of a similar usage of temporary anonymous hashes see. Re: Re: Re: Unique values in array.
    HTH

    _________
    broquaint

Re: Explanation of mapping and undef
by bart (Canon) on Jun 08, 2004 at 11:15 UTC
    It's creating an anonymous array, just like
    %hash = map {$_ => undef } qw(city state country);
    which produces a list like
    ( 'city' => undef, 'state' => undef, 'country' => undef )
    which is then turned into a hash. In fact, any other value than undef would do just as well, as it isn't actually used.

    But, it does so for every loop, just to test if $field is one of qw(city state country). That's a very inefficient way of doing it.

    A better way would be to create the hash outside of the loop:

    my %skip = map {$_ => undef } qw(city state country); foreach my $field (param) { next if exists $skip{$field}; foreach my $value (param($field)) { #process non blank thedata variable ... } }

    Or, IMO perfectly acceptable for small skip lists and/or few parameters:

    foreach my $field (param) { next if grep { $field eq $_ } qw(city state country); foreach my $value (param($field)) { #process non blank thedata variable ... } }

    Note that I moved the test outside of the inner loop, as the result won't change for whatever values you get.

      While it's true that any value would be ok, undef is generally preferred because there is one undef scalar that all undef values point to. This results in a small savings in memory, as well as being more descriptive.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: Explanation of mapping and undef
by calin (Deacon) on Jun 08, 2004 at 11:15 UTC
    map { $_ => undef } qw(city state country) creates the list (city => undef, state => undef, country => undef). This is an idiomatic way to initialize a hash from a list of values (used as keys).

    Anyway, the code:

    next if exists { map {$_ => undef } qw(city state country) } -> { $field };

    is redundant and too 1337 for its own good. I would write:

    next if grep {$_ eq $field} qw(city state country);

    Update: oops, my mind was captured by the other grep :)

      Thanks!