Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Location of Conditional test effects results

by chakram88 (Pilgrim)
on Apr 10, 2007 at 19:13 UTC ( [id://609235]=perlquestion: print w/replies, xml ) Need Help??

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

Oh revered monks, I come seeking knowledge and wisdom.

Quick description of my 'issue:

I can take the same block of code, and move one line (a conditional operator) from one point to another, and I end up with a different result.

My Data structure is an AoH, where a Hash element 'could' be an array. The conditonal is testing for the existance of that secondary array. I loop over the AoH.

With the conditional operator assignment at the top of my loop, I get the expected results based on the test in the conditional. If I move the conditional assignment to the end of my loop (no data changes within the loop), I get responses as if the conditional were always true.

Code whittled down (line marked with <------ is the offending little bugger)

#!/usr/bin/perl -l use warnings; use strict; my $records = [ { 'services' => [], 'zone_record_id' => '1', }, { 'services' => [ { 'status' => 'OK', 'id' => '0', 'class' => 'Primary' } ], 'zone_record_id' => '2', }, { 'services' => [ { 'status' => 'OK', 'id' => '1', 'class' => 'Editable' } ], 'zone_record_id' => '4', }, { 'services' => [ { 'status' => 'OK', 'id' => '1', 'class' => 'Secondary' } ], 'zone_record_id' => '5', }, ]; my $lbr = "\n=============\n"; foreach my $record (@$records) { my $editor; print $lbr, "Record: $record->{'zone_record_id'}"; # Conditional array defined check first $editor = (@{$record->{'services'}})? 'service_edit' : 'plain_edit +'; # <--- $editor = "no editor" if $record->{'services'}[0]{'class'} eq 'Pri +mary'; $editor = "no editor" if $record->{'services'}[0]{'class'} eq 'Sec +ondary'; # place here for 'Try to define all 'no editor' situations first print $editor; }
Results:
Conditionaly check for defined array first: ============= Record: 1 plain_edit ============= Record: 2 no editor ============= Record: 4 service_edit ============= Record: 5 no editor Try to define all 'no editor' situations first: ============= Record: 1 service_edit ============= Record: 2 service_edit ============= Record: 4 service_edit ============= Record: 5 service_edit

Yes, I know that the eq test is putting up 'undefined' warnings on those $records where the secondary array is not defined. I deal with it in my full code, this is just "narrowed down to the least amount of code to reproduce the problem".

P.S. I had a difficult time coming up with an appropriate title, so any suggestions welcome

Replies are listed 'Best First'.
Re: Location of Conditional test effects results
by ferreira (Chaplain) on Apr 10, 2007 at 19:43 UTC
      Well, sure, it's clear now. Thanks for the explanation, and lots of info to absorb.
Re: Location of Conditional test effects results
by shmem (Chancellor) on Apr 10, 2007 at 19:58 UTC
    You are falling prey to auto-vivification. After the lines
    $editor = "no editor" if $record->{'services'}[0]{'class'} eq 'Pri +mary'; $editor = "no editor" if $record->{'services'}[0]{'class'} eq 'Sec +ondary';

    the array element @{$record->{'services'}} contains one element - an anonymous hash holding at least the key class whose value might be undef.

    You are looking at the value of $record->{'services'}[0]{'class'}, but to do that the key class in the hash %{$record->{'services'}[0]} has to exist, so perl just allocates the hash and the key for you. After that, the anonymous array has at least one element.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

        Yes, I know that the eq test is putting up 'undefined' warnings on those $records where the secondary array is not defined. I deal with it in my full code,

        Had you fixed them, you would have fixed your problem too. Do not lightly ignore warnings in Perl.

Re: Location of Conditional test effects results
by graff (Chancellor) on Apr 11, 2007 at 05:06 UTC
    Nobody (yet) has mentioned how your code could have been written to fix the mistake, so I'll do it ;)
    for my $record (@$records) { my $editor; print $lbr, "Record: $record->{'zone_record_id'}"; if ( @{$record->{services}} == 0 ) { $editor = 'plain edit'; } elsif ( $record->{services}[0]{class} =~ /Primary|Secondary/ ) { $editor = 'no editor'; } else { $editor = 'service edit'; } print $editor; }
    The point being: once you establish that you've reached an empty slot at a given point in your structure, you may want to avoid going any deeper down that particular path, unless you really do want to create new structure where none existed previously.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://609235]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2024-04-19 23:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found