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

Hi Monks!
I just need to confirm if I am doing the right thing here. All I want is to get out of the "for loop" if there is no email address. Is that the right way?
for (my $i = 0; $i < @{$data}; $i++) { my $email = $data->[$i]{'email'} || ''; my $name = $data->[$i]{'name'} || ''; if($email eq '') { bad("No email address."); last; }else{ good("Email found."); } }

Thanks!

Replies are listed 'Best First'.
Re: Get out of "For Loop"!
by roboticus (Chancellor) on Oct 12, 2010 at 18:29 UTC

    Only if you don't want to process the rest of the items in @$data. I suspect you really want to use next instead of last so you can advance to the next one.

    Further, that's a rather C-ish loop. Might I suggest something like this:

    for my $item (@$data) { if (defined($$item{email}) and $$item{email} ne '') { good("Email found."); } else { bad("No email address."); next; } ...other stuff... }

    ...roboticus

      There's no reason to separate the error check from the error message in this code.
      for my $item (@$data) { if (!defined($item->{email}) || $item->{email} eq '') { bad("No email address."); next; } good("Email found."); ...other stuff... }
Re: Get out of "For Loop"!
by NetWallah (Canon) on Oct 12, 2010 at 19:55 UTC
    I'm assuming you want to do something useful with the list of cases where there is "No email address". If so, 'map' is your friend:
    my @names_with_no_email = map {$_->{email} eq '' ? $_->{name}:()} @$ +data;

         Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

        chromatic,
        Why map and not grep?

        Perhaps I am missing something, but grep doesn't look reasonable here. This is both filtering and transforming which makes me think map. In addition to filtering hash references based on the 'email' key, it returning the value of the 'name' key. I can't think of a way to do that with grep that is clear but please feel free to elucidate me?

        Cheers - L~R

Re: Get out of "For Loop"!
by girarde (Hermit) on Oct 13, 2010 at 19:08 UTC
    This being Perl there are several right ways. Another one would be:

    for (my $i = 0; $i < @{$data}; $i++) { my $email = $data->[$i]{'email'} || ''; my $name = $data->[$i]{'name'} || ''; unless ($email) { bad("No email address."); last; }else{ good("Email found."); } }

    This does not test for validity of the email, of course, but presumably you do that elsewhere. And presumably the good and bad subroutines are defined somewhere.

      But to quote from one of the holy books (Perl Best Pratices, Chapter 6.4):
      Don't use unless or until at all.

      So instead if unless($email) rather use if(! $email)

        Damian is sometimes wrong. Shhh! Don't tell anyone.

        I prefer unless() as a suffix. I do agree that an unless() block should not have an else ... negating the negation warps my mind this early on a Monday morning. But it doesn't need one, since the next / last goes to the next iteration of the loop.

        As Occam said: Entia non sunt multiplicanda praeter necessitatem.