Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Logic Issues with conditionals

by jmneedhamco (Novice)
on Mar 27, 2015 at 14:05 UTC ( [id://1121511]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings:

I am working on a script that updates some files for user access on a propritory system. Basically, I need to update 12 files based on some very weird logic.

The English version is as follows: for fileset 1, append file with user string. for fileset 2, append file with user string. these are always done together if developer access. for fileset 3, append file with user string, only if production access. Fileset four is appended with user string, and is different from filesets 1 - 3. if filesets 1 - 3 are appended, push script must be run, if fileset 4 no push.

above is highly simplified from the real situation but the 'user strings' mentioned differ. There are four databases that are used, I will call them db1, db2, db3 and db4 for my code. So the jist of what I tried is a nested loop. I am having trouble with the second part of the developer access. Basically, it needs to run an outer loop for all three instances. But if Production is not needed, the loop should terminate. This is done inside another "master loop" that does this foreach user in an input file. I also set a flag variable to try to make this work.

Code I tried (not complete script):
if($access eq 'prod' || $access eq 'dev') { if($access eq 'dev') { $flag = "dev"; } for(my $i = 0; $i < 3;$i++) { if($flag eq 'dev') { @files = ('file1', 'file2', 'file3', 'file4'); } elsif($i == 2) { $flag = "reporting"; @files = ('file1', 'file2', 'file3', 'file4'); } if($access eq 'prod') { $flag = "prod"; @files = ('file1', 'file2', 'file3', 'file4'); } else { break; } for (my $j = 0; $j < 4; $j++) { my $file = $files[$j]; my $db = $dbs[$j]; print("j variable is: $j\n"); $acString = &build_string($user, $db, $flag); &WriteFile($file, $acString); } } }

The build string sub puts the string to append to the file together (first run through inner loop is db1). Then it calls the writefile sub and appends the string to the file that is passed in from the fileset (@files).

Again, this is done for however many users are read in from an input file which is ARGV[0].

Hope someone can help me sort this out. Thanks in advance for the help all!

Replies are listed 'Best First'.
Re: Logic Issues with conditionals
by choroba (Cardinal) on Mar 27, 2015 at 14:45 UTC
    In a for-loop, you don't need break, you need last.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Logic Issues with conditionals
by Athanasius (Archbishop) on Mar 27, 2015 at 15:33 UTC

    Hello jmneedhamco,

    So the jist of what I tried is a nested loop.

    I suspect that is the wrong approach here. A structure like this:

    for(my $i = 0; $i < 3;$i++) { if(...) { ... } elsif($i == 2)

    always raises a red flag for me: if you have to treat the case where $i == 2 differently, why try to incorporate it in a loop with the other cases? I think you’d be better off handling the 3 (or should it be 4?) file sets separately.

    Also note that this:

    for (my $j = 0; $j < 4; $j++) { my $file = $files[$j]; ...

    is better expressed in Perl using a foreach loop:

    for my $file (@files) { ...

    And please note that by calling &WriteFile($file, $acString) with an initial &, you are bypassing its prototype (if any). Unless you have a good reason to do so, it’s better practice to omit the ampersand: WriteFile($file, $acString).

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Logic Issues with conditionals
by fishmonger (Chaplain) on Mar 27, 2015 at 15:07 UTC

    I'd cleanup your @files assignments via the use of a hash. Something like this:

    my %files = ( dev => [qw(dev_file1 dev_file2 dev_file3 dev_file4)], prod => [qw(prod_file1 prod_file2 prod_file3 prod_file4)], report => [qw(report_file1 report_file2 report_file3 report_file4) +], ); my $files = $files{$access};

    I might even extend it to be a dispatch table, but you haven't provided enough info to say if that would be a good approach in your case.

      thanks for the input Fishmonger! I decided this will be the way to go. I am just having one issue as I am not very familar with hashes at all. Been doing Perl things for quite a while, but hashes or key-value pairs never crossed my mind as a hash of arrays.

      that said, I figured out how to get the access part or key out of the hash, but I need to now address the elements of the arrays. For example: If I pull the keys into an array, then I can address them. Maybe there is a more direct way, and that would be nice too. But I also need to figure out how to get say element 0 from the dev array. Help is appreciated!

      my %files = ( dev => [qw(testd.txt testd1.txt testd2.txt testd3.txt)], prod => [qw(testp.txt testp1.txt testp2.txt testp3.txt)], report => [qw(testr.txt testr1.txt testr2.txt testr3.txt)], qptool => [qw(testq.txt testq1.txt testq2.txt testq3.txt)], ); @flags = keys %files;

      This gets the keys from the hash.

        There are multiple ways to access the array elements. The most direct would be:

        my %files = ( dev => [qw(dev_file1 dev_file2 dev_file3 dev_file4)], prod => [qw(prod_file1 prod_file2 prod_file3 prod_file4)], report => [qw(report_file1 report_file2 report_file3 report_file4) +], ); print $files{dev}[0];

        or you could do this

        my @dev = @{ $files{dev} }; print $dev[0];

Re: Logic Issues with conditionals
by GotToBTru (Prior) on Mar 27, 2015 at 15:51 UTC

    I'm with Athanasius on this one. There might be a clever way to make it work in a single loop. But I would prefer to go the wordier route for the sake of clearer documentation. The time spent in writing and later reading/modifying the code is significant compared to the time it will take to execute. Be good to yourself (and any future maintainers). Treat cases separately any time they would make your if clauses start to look like spaghetti.

    Dum Spiro Spero
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-25 09:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found