cLive ;-) has asked for the wisdom of the Perl Monks concerning the following question:

I want to create a hash on the fly in the middle of a large CGI print statement. I can easily do it outside of the print statement, but within the print statement I can only do it like this:

print $q->p( $q->scrolling_list( -name => 'list_input', -values => [0..$#array], -size => 1, -labels => { # yuck, using uninitialized global map { $::i++, $_ } @array } ) );

and I shudder at the thought of using a global. Any other suggestions on how to do this, or should I quit being lazy and just build the hash outside the print statement :) ?

cLive ;-)

Replies are listed 'Best First'.
Re: lazy map question
by diotalevi (Canon) on Mar 15, 2004 at 19:34 UTC

    Use indexes instead.

    print $q->p( $q->scrolling_list( -name => 'list_input', -values => [0..$#array], -size => 1, -labels => { map { $_, $array[$_] } 0 .. $#array } ) );

      d'oh... of course... need more coffee...

      cLive ;-)

Re: lazy map question
by BrowserUk (Patriarch) on Mar 15, 2004 at 19:34 UTC

    Substitute this for your map

    do{ my %h; @h{ 0 .. $#a } = @a; %h };

    Or better, omit the curlies around the map and pass the reference direct.

    do{ my %h; @h{ 0 .. $#a } = @a; \%h };

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
Re: lazy map question
by iburrell (Chaplain) on Mar 15, 2004 at 22:26 UTC
    I would suggest pulling out the creation of the hash out of the print statement. Create a lexical variable. Since you are using the range twice, it might make sense to assign that to a lexical.
    my @values = [ 0 .. $#array ]; my %labels = map { $_, $array[$_] } @values; print $q->p( $q->scrolling_list( -name => 'list_input', -values => \@values, -size => 1, -labels => \%labels, ) );
Re: lazy map question
by waswas-fng (Curate) on Mar 15, 2004 at 19:35 UTC
    I tend to do it right before the print statements -- simple maps may be easy to insert inline like above (never mind the yuck part), but many times it requires more complicated code. There is a lot to be said for readability and standardizing the order you do it in -- if you have to build it once ahead of time consider doing it every time so your code flows the same.


    -Waswas
Re: lazy map question
by cormac (Acolyte) on Mar 15, 2004 at 21:02 UTC
    Please, for style's sake, consider diotalevi's approach using map, or ditching the array altogether and using a hash. Why make CGI code more kludgy than it is, to begin with?

    UPDATE: I have decided to make myself useful, and contribute the following:

    The phash function from our fields pragma can be used to safely contort our array into a (pseudo)?hash. The first argument in my example consists of an anonymous array reference of known keys for the values' extracted from said array. This anonymous arrayref can quite easily be replaced by a reference to a splice of our array: be creative, remember: tmtowtdi.

    use fields qw{ phash }; [...] print $q->p( $q->scrolling_list( -name => 'list_input', -values => \@array, -size => 1, -labels => { fields::phash([key0 key1 key], \@array) }, ) );
Re: lazy map question
by cLive ;-) (Prior) on Mar 15, 2004 at 19:43 UTC

    Well, I found one way that's a little messy.

    print $q->p( $q->scrolling_list( -name => 'list_input', -values => [0..$#array], -size => 1, -labels => { map { $#array--, $array[-1] } @array } ) );

    Just as long as I don't use the array later and rely on $#array I'll be set lol. This is bugging me now

    cLive ;-)