Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Error Unitialized value and use

by tryingnottofailmytes (Novice)
on Dec 08, 2015 at 05:16 UTC ( [id://1149642]=perlquestion: print w/replies, xml ) Need Help??

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

So I'm getting an error saying two of my variables are unintilized when I initilize them at the beginning. Also advice for adding a use for a module. I tried lib '/Desktop/perl/final/ where I have it stored, but it didn't work. this is the code.
#!/usr/bin/perl -w use strict; #use beginperlforbioinfo; my $annotation = ''; my $dna = ''; my $record=''; my $filename = "record.gb"; my $save_input_separator = $/; unless (open(GBFILE, $filename)) { print "Cannot open Genbank file "; exit; } #use the input seperator //\n to read a entire file to scalar $/ = "//\n"; $record= <GBFILE>; #print $record; #always to remember to reset the file input seperator $/= $save_input_separator; #to seperate the annotation from sequence ($annotation, $dna) = ($record =~ /^(LOCUS.*ORIGIN\s*\n)(.*)\/\/\n/s); print "$annotation, $dna\n";
not sure how to make the module work and why I'm getting "Use of uninitialized value $annotation in print at parse.pl line 28, <GBFILE> line 1. Use of uninitialized value $dna in print at parse.pl line 28, <GBFILE> line 1. " errors.

Replies are listed 'Best First'.
Re: Error Unitialized value and use
by kcott (Archbishop) on Dec 08, 2015 at 06:15 UTC

    G'day tryingnottofailmytes,

    Well, you do initialize them near the beginning of your script:

    my $annotation = ''; my $dna = '';

    Their next appearance in your script is:

    ($annotation, $dna) = ($record =~ /^(LOCUS.*ORIGIN\s*\n)(.*)\/\/\n/s);

    where, presumably, you're setting both to undef (i.e. uninitialized).

    When you then use them in the print statement on the following line:

    print "$annotation, $dna\n";

    you get a warning about this.

    For the other part of your question, see the use documentation.

    — Ken

Re: Error Unitialized value and use
by GrandFather (Saint) on Dec 08, 2015 at 07:14 UTC

    Ignoring the module issue for the moment because you don't show what's in it, there are a few things to improve with your code as it stands:

    #!/usr/bin/perl use strict; use warnings; my $filename = "record.gb"; open my $fOut, '>', $filename or die "Failed to create $filename: $!\n +"; print $fOut <<STR; LOCUS some guff ORIGIN Another line of guff // STR close $fOut; open my $fIn, '<', $filename or die "Failed to open $filename: $!\n"; #use the input seperator //\n to read a entire file to scalar my $record = do {local $/ = "//\n"; <$fIn>}; #to seperate the annotation from sequence $record =~ /^(LOCUS.*ORIGIN\s*\n)(.*)\/\/\n/s or die "Malformed record + '$record'\n"; my ($annotation, $dna) = ($1, $2); print "$annotation, $dna\n";

    Prints:

    LOCUS some guff ORIGIN , Another line of guff

    The first block of file related stuff is just to create a file containing some test data. If you want people to be able to reproduce your issues you have to provide all the bits required. Using the script itself to generate any files you may need helps with that.

    Notice that the variables are declared where they are first needed and generally they are assigned a real value at that time. Always declare variables where they are needed and no sooner so it's easy to see how they are used.

    Notice that the file open statements use lexical file handles (my $fIn) and three parameter open (see open). It's also generally a good idea to die for I/O errors and report the file you were opening and the error generated by the system.

    The my $record = do {local $/ = "//\n"; <$fIn>}; line localises $/ so that it can be changed within the do {} block without affecting the value of $/ outside the block. That makes changing $/ much safer and the scope of the change completely clear.

    The root of your "Use of uninitialized value" error is that the match didn't find anything to match. Again, use die to report the error and give the context so figuring out what broke is easier.

    Notice that annotation and dna variables are declared as a list and are assigned the values of match variables 1 and 2 after a successful match.

    Premature optimization is the root of all job security
      ... annotation and dna variables are declared as a list and are assigned the values of match variables 1 and 2 after a successful match.

      Note that it's also possible to "capture the captures" to lexicals and die on match failure in a single statement:

      c:\@Work\Perl\monks>perl -wMstrict -le "for my $record (qw(eks---wye eks---wyyye)) { my ($x, $y) = $record =~ m{ \A (eks) .* (wye) \z }xms or die qq{malformed record '$record'}; ;; print qq{record '$record': got '$x' '$y'}; } " record 'eks---wye': got 'eks' 'wye' malformed record 'eks---wyyye' at -e line 1.
      I prefer this practice because it's all too possible, believe me, to insert just one more pattern match test between the original capturing statement and the separate statement intended to assign its capture variables  $1 $2 ... to lexicals, in which case the original capture groups sometimes, but not always, and perhaps quite silently (gotta love this bug!), become invalid.


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

Re: Error Unitialized value and use
by AnomalousMonk (Archbishop) on Dec 08, 2015 at 06:05 UTC
    ... it didn't work.

    Exactly what is "it"? Exactly how did it "not work"?

    ... my variables are unintilized when I initilize them at the beginning.

    You assign values at the beginning, but then you assign again from the result of a match, and that's probably where the undefined values come from: regex captures return undef when the match fails. (Update: More precisely, a failed match in list context, as below and in the OPed code, returns an empty list, which, when assigned to scalar variables, yields undefs.) You have to test the success of the match somehow:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $s = 'eks---wye'; ;; my $found = my ($x, $y) = $s =~ m{ \A (eks) .* (wye) \z }xms; if ($found) { print qq{A: found '$x' and '$y'}; } else { print 'A: found nada'; } ;; $s = uc $s; ;; if (my ($xx, $yy) = $s =~ m{ (EKS) .* (WYE) }xms) { print qq{B: found '$xx' and '$yy'}; } else { print 'B: found nada'; } " A: found 'eks' and 'wye' B: found 'EKS' and 'WYE'
    Play with that, change the string value and the match regexes, until you're confident of what's going on. (Of course, there are other ways to test match success.) The usual links: perlre, perlretut, and perlrequick.


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

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2024-04-24 01:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found