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

I recently wrote:
defined(%stores) ? ( $wml = join "<br/>\n",map { "<a href='$params{URL +}/op?optin&amp;store=$_'>$stores{$_}->{'store_t_address'}</a>" }(keys + %stores) ): $wml = "Pas de résultat<br/><br/>" ;

Notice the brackets. Well, that won't work: perl complains about having a list on one part , and a scalar on the other.
I found it very strange hence my posting: is that normal ?

Replies are listed 'Best First'.
•Re: the ? : operator : a bug ?
by merlyn (Sage) on Nov 21, 2002 at 11:57 UTC
      oops. I often use it the way I showed above as a shortcut, but I realize now why it's wrong.
      Thanks.
Re: the ? : operator : a bug ?
by broquaint (Abbot) on Nov 21, 2002 at 12:02 UTC
    This is a precedence issue
    shell> perl -MO=Deparse,-p - defined(%stores) ? ( $wml = join "<br/>\n",map { "<a href='$params{URL +}/op?optin&amp;store=$_'>$stores{$_}->{'store_t_address'}</a>" }(keys + %stores) ): $wml = "Pas de résultat<br/><br/>" ; ^D Assignment to both a list and a scalar at - line 2, near ""Pas de résu +ltat<br/><br/>" ;" - had compilation errors. ((defined(%stores) ? ($wml = join("<br/>\n", map({"<a href='$params{'URL'}/op?optin&amp;store=$_'>$stor +es{$_}{'store_t_address'}</a>";} keys(%stores)))) : $wml) = "Pas de r\351sultat<br/><br/>");
    As you can see in the B::Deparsed code (with the output slightly formatted) the assignment is occurring outside the ?: statement. Just put parentheses around the last statement and it should work fine.
    HTH

    _________
    broquaint

Re: the ? : operator : a bug ?
by UnderMine (Friar) on Nov 21, 2002 at 12:10 UTC
    $wml = defined(%stores) ? (join "<br/>\n",map("<a href='$params{URL}/o +p?optin&amp;store=$_'>$stores{$_}->{'store_t_address'}</a>" , keys %s +tores) ):"Pas de résultat<br/><br/>" ;
    Any reason for this convoluted code ? and would it not be nicer as :-
    if (defined(%stores)) { my @param = map("<a href='$params{URL}/op?optin&amp;store=$_'>$store +s{$_}->{'store_t_address'}</a>" , keys %stores) $wml = join "<br/>\n", @param; } else { $wml = "Pas de résultat<br/><br/>"; }

    Hope it helps
    UnderMine

      No particular reason, i guess it was just out of laziness that I used a not so shortcut
Re: the ? : operator : a bug ?
by Sihal (Pilgrim) on Nov 21, 2002 at 13:14 UTC
    Thanks for the insight.
    As you all said, the key to solving this is either to remove the brackets, or add them in the 3rd part of the statement or not using it in void context. I was aware of that, but thanks for explaining why it actually did that.
    Merlyn, I noticed several of your posts urging not to use stuff (namely map) in void context. Could you explain why it is so "dangerous"?

      Using Perl operators in void context is like calling up the reference desk of your local library and asking, "What's the average bodily temperature of a healthy aardvark on the moon of Pluto during the rainy season?" The poor librarian will have to find a large enough population of aardvarks to have a control set and a test set, not to mention mounting an expedition to Pluto with space thermometers and the like. We won't even get into the fact that wet aardvarks in space are surly! When the researcher finally returns to the phone to say, "Slightly lower than on earth," you'll say. "Thanks, but I just wanted to know if this was the right phone number."

      In other words, don't do a bunch of work just to throw it away.

        This is probably partly Perls fault since it lets you, and encourages you to, write stuff like do something || die "Message";. That could be called using the or operator in void context. Even more so when it isn't a die, but a warn or print afterwards.

        I know that when I first started with Perl, coming from other languages, I used a lot of stuff in void context that I wasn't supposed to, both map and ?: because it let me, and the documentation didn't point out that it was a bad thing. That I learnt from other coders, at this place.

        Not that I am defending it, I've leant my lesson. But I do think that the nature of the language seems to encourage such things. :)


        You have moved into a dark place.
        It is pitch black. You are likely to be eaten by a grue.
      From perldoc -q map

      Found in /System/Library/Perl/pods/perlfaq6.pod

      What's wrong with using grep or map in a void context?

      Both grep and map build a return list, regardless of their context. This means you're making Perl go to the trouble of building up a return list that you then just ignore. That's no way to treat a programming language, you insensitive scoundrel!

      That's in 5.6.0, but apparently it's changed in 5.8.0, go figure.

        :-) Sorry.
        But actually the root of evil was that I didn't really understand how ? : worked. I thought of it as a nice shortcut but didn't see how it really worked. Which is why I was puzzled yesterday.