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

Hello wise monks! I come to ask for your kind advice and enlightenment on the following matter:

I've been trying to print a character a certain number of times, if a certain condition is met. For the printing, I use an “until” loop. For the condition, I would like to use the conditional (ternary) operator. However, this apparently results in a syntax error. Below is example code which produces the error. My intention was to print the equals sign ten times instead.

#!/usr/bin/perl use strict; use warnings; my $count = 0; ( defined $count ) ? ( print "=" until ( $count ++ == 10 ) ) : ( print "Undefined count.\n" );

This results in the error: syntax error at ./example.pl line 8, near ""=" until". I have tried using a different form for the loop:

( defined $count ) ? ( until ( $count ++ == 10 ) { print "=" } ) : ( print "Undefined count.\n" );

However, that results in a similar error: syntax error at ./example.pl line 8, near "( until". When I try to achieve this using “if” and “else”, it works very well, using this code:

if ( defined $count ) { print "=" until ( $count ++ == 10 ); } else { print "Undefined count.\n"; }
Is it possible to use such constructions within the conditional (ternary) operator, as I've been trying to do? And if yes, how may I do so correctly? Thank you in advance!

Replies are listed 'Best First'.
Re: Compound statements within the conditional (ternary) operator (updated)
by AnomalousMonk (Archbishop) on Apr 14, 2018 at 12:27 UTC

    The basic problem is that you're trying to give  ?: a statement where the operator expects an expression. Try something like these:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $count; F(); ;; $count = 0; F(); ;; sub F { defined $count ? do { print '=' until $count ++ == 5; } : print 'Undefined count' ; } " Undefined count = = = = = c:\@Work\Perl\monks>perl -wMstrict -le "my $count; F(); ;; $count = 0; F(); ;; sub F { print defined $count ? '=' x 5 : 'Undefined count'; } " Undefined count =====
    The second example does not keep track in  $count of the number of  '=' characters printed and you may need this for some reason, but if you don't, the second example is the way I'd go.

    Update: If you do want to keep track of the number of things printed, here's a variation on the second method:

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my $count; F(); dd $count; ;; $count = 0; F(); dd $count; ;; sub F { print defined $count ? '=' x ($count += 5) : 'Undefined count'; } " Undefined count undef ===== 5


    Give a man a fish:  <%-{-{-{-<

Re: Compound statements within the conditional (ternary) operator
by roboticus (Chancellor) on Apr 14, 2018 at 19:52 UTC

    Fendo:

    You've already got some good answers, but in the spirit of "we've a plethora of ways to do it", you could simply compute the number of "=" signs that you want, and then build a list of them like this:

    print defined($count) ? ("=") x (10-$count) : "Undefined count.\n";

    Of course, if you calculate the number of "=" symbols you want, then you could also do it as:

    print defined($count) ? substr("==========", $count) : "Undefined count.\n";

    However, once you try it, you'll notice that your printing is off because you're sometimes putting in a "\n" and sometimes not. If you want to always put in the "\n", you could do it like:

    print defined($count) ? ("=") x (10-$count) : "Undefined count.", "\n"; print defined($count) ? substr("==========", $count) : "Undefined count.", "\n";

    You could crunch them up into a single line, too:

    print defined($count) ? ("=") x (10-$count) : "Undefined count.", "\n" +; print defined($count) ? substr("==========", $count) : "Undefined coun +t.", "\n";

    but then it's easy to miss that there are two expressions generating arguments for the print statement and/or easy to confuse the boundary between them.

    Sometimes, though, it just simplifies things overall to break things apart a bit. Most of the time, I'd simply do something like:

    if (! defined $count) { print "Undefined count.\n" } else { print substr("==========", $count) }

    But I do see the natural desire to make the printing front-and-center rather than the conditional logic. I'll frequently do so when the logic is pretty basic:

    print "You bought $qty item", $qty>1 ? "s" : "", " today!\n";

    But when there's too much logic in formatting something to print, it's often better to do the decisioning earlier, then assemble the bits into your print statement:

    my $item = $qty > 1 ? "items" : "item"; my $num = num_to_text($qty); my $when = "today"; $when = "yesterday" if $purchase_date == $yesterday; print "You bought $num $item $when!\n";

    Sigh ... I think I'll stop now, or I'll go off on another tangent...

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      A minor nit: I don't know about other Englishes, but for Yank-Canuck and I think Brit English usage, I would construct the plural slightly differently:

      c:\@Work\Perl\monks>perl -wMstrict -le "for my $qty (0 .. 3) { printf qq{you bought $qty item%s today \n}, $qty == 1 ? '' : 's'; } " you bought 0 items today you bought 1 item today you bought 2 items today you bought 3 items today


      Give a man a fish:  <%-{-{-{-<

        AnomalousMonk:

        Yep, if $qty kan be naught, then yer code would be more Englishy. ;^)

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

Re: Compound statements within the conditional (ternary) operator
by mr_ron (Deacon) on Apr 14, 2018 at 13:02 UTC

    Mostly what AnomalousMonk said. The first paragraph on ?: in Programming Perl (4th ed) talks about it being an operator and expression similar to if-then-else which is a flow control statement. A hopefully simpler example:

    use Modern::Perl; my $count = 0; print defined $count ? do { my $s = ''; $s .= '=' until $count++ == 10; $s } : "Undefined count.\n";
    Ron