Home > Enterprise >  In Perl, can I put unlimited conditions with the ternary conditional operator?
In Perl, can I put unlimited conditions with the ternary conditional operator?

Time:11-25

I have some struggle with a piece of code. It's about the ternary operator in perl. I can't figure out how to set more conditions on it. Literally, I don't really understand the expression.

my $class = $user_name ? '' : (grep { $_ eq $task_id } @tasks_todo) ? ' : 'class="crossed"';

I would like to put another condition with my new variable which should be like:

$required ? '' : '' : ''

$required is of type Mojo:Collection and represents a set type data which is fetched by a query.

Can someone explain me the conditions below and tell me if I can put another condition on the ternary operator? How many conditions are allowed and what is the best practice to use the ternery operator?

CodePudding user response:

Whoever wrote that is too clever for their own good.

When you run into complicated logic like this, you don't lose anything by taking it apart a bit and putting it in a dedicated method you can test individually. By returning only the class name instead of the filled in attribute value, you make it easier to use the return value even if that means it now becomes the caller's responsibility to write push @classes, css_class(...) followed by a sprintf 'class=%s', join(' ', @classes); or similar.

#!/usr/bin/env perl

use strict;
use warnings;

use List::Util qw( any );
use Test::More;

sub css_class {
    my ($user_name, $task_id, $tasks_todo) = @_;

    return '' unless $user_name;

    if (any { $task_id eq $_ } $tasks_todo->@*) {
        return 'todo';
    }

    return 'crossed';
}

my @cases = (
    {
        args => [undef, 'blah', []],
        expected => '',
    },
    {
        args => ['bob', 'notdone', ['notdone']],
        expected => 'todo',
    },
    {
        args => ['bob', 'done', ['notdone']],
        expected => 'crossed',
    },
);

for my $case (@cases) {
    is css_class($case->{args}->@*), $case->{expected};
}

done_testing;

Output:

$ prove -v pp.pl
pp.pl ..
ok 1
ok 2
ok 3
1..3
ok
All tests successful.
Files=1, Tests=3,  0 wallclock secs ( 0.08 usr    0.03 sys =  0.11 CPU)
Result: PASS

CodePudding user response:

if $username is set, the $class-Variable is set to empty, otherwise, if the $task_id is in the @task_todos $class is set to ''and if neither is true, $class is set to ''.

You can add an arbitrary number of conditions in an expression with the ternary operator, but you should consider adding at least some whitespace to make it more readable, though putting it in if/then/else would be even better.

my $class = $user_name 
             ? ''  
               : (grep { $_ eq $task_id } @tasks_todo) 
                  ? ' 
                    : 'class="crossed"';

CodePudding user response:

I solved my problem by adding a new condition underneath after the example gived earlier.

use List::Util qw/any/;
my $class = "";
unless ($user_name) {
   if (any { $_ eq $task_id } @tasks_todo) {
      $class = ''; 
   } 
   else
   {
     $class = '';
   }
   if ($required ne $month) {
     $class = ''
}

This did the trick, either I changed my Query and so i get the right things in order.

  •  Tags:  
  • perl
  • Related