Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Text Analysis: given(){when(){}} block throws a 'useless use of private variable...etc' error

by biohisham (Priest)
on Oct 18, 2010 at 13:14 UTC ( [id://865927]=perlquestion: print w/replies, xml ) Need Help??

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

The following code does what is required to be done however it keeps throwing an error => 'useless use of private variable in void context at line 21', this behavior showed up after I switched from using some disjointed if statements into a more compound given(){when(){}} construct. Frankly, I am at a total loss on how to resolve this, tried looking around for similar situations but the problem presentation was different and the replies just added to the confusion...

So fellow monks, I present before you the code after having become spent for my efforts with some records from the tab-delimited dataset, the combination of the code conditionals reflect whether or not some entries in the columns SNP, Allele1 and Allele2 are missing, and seeking your explanation on why this error arises and how to go about resolving it I afford you my appreciations and the kindest of gratitude ..

#!/usr/local/bin/perl use strict; use warnings; use Data::Dump qw(pp); use feature qw(switch say); my $path = "testSample.txt"; open(FH, $path) or die("error, $!\n"); my (%hetero, %homo, %unclassified); until(eof(FH)){ my ($file, $patientName, $panel, $snp, $allele1, $allele2, $siz +e1, $size2)= split "\t", <FH>; $snp ||='';$allele1 ||= ''; $allele2||=''; #if not initialized + set to '' chomp($snp); $snp = 'missed' if $snp eq ''; given($allele1, $allele2){ when($allele1 ne '' && $allele2 ne ''){constructHetero +($snp, $patientName, $allele1, $allele2)} when($allele1 ne '' && $allele2 eq ''){constructHomo(' +type1', $snp,$patientName, 'allele1', $allele1)} when($allele1 eq '' && $allele2 ne ''){constructHomo(' +type2', $snp,$patientName, 'allele2', $allele2)} when($allele1 eq '' && $allele2 eq ''){constructUnclas +sified($snp, $patientName)} } } sub constructHetero{ my ($snp, $patientName, $allele1, $allele2) = @_; $hetero{$snp}{$patientName}{'allele1'}=$allele1; $hetero{$snp}{$patientName}{'allele2'}=$allele2; $hetero{$snp}{$patientName}{'records'}++; $hetero{$snp}{'total_records'}++; }; sub constructHomo{ my ($type, $snp, $patientName, $alleleNumber,$allele)=@_; $homo{$type}{$snp}{$patientName}{$alleleNumber}=$allele; $homo{$type}{$snp}{$patientName}{'records'}++; $homo{$type}{$snp}{'total'}++; $homo{$type}{'total_records'}++; } sub constructUnclassified{ my($snp, $patientName)=@_; $unclassified{$snp}{$patientName}{'records'}++; $unclassified{$snp}{'total'}++; $unclassified{'total_records'}++; } #print pp(\%hetero); #print pp(\%homo); #print pp(\%unclassified);
testSample.txt Sample File Sample Name Panel SNP Allele 1 Allele 2 +Size 1 Size 2 011.fsa MS-039 Panel_3130 012.fsa MS-039 Panel_3130 31.76 014.fsa MS-291 Panel_3130 rs7577363 90.79 92.46 013.fsa MS-291 Panel_3130 rs7577363 006.fsa MS-290 Panel_3130 rs10735781 G 78.69 80. +31 005.fsa MS-290 Panel_3130 rs10735781 G 78.85 80. +32 011.fsa MS-039 Panel_3130 rs10735781 C 78.63 80. +1 001.fsa MS-148 Panel_3130 rs10735781 C G 78.57 80 +.2


Excellence is an Endeavor of Persistence. A Year-Old Monk :D .
  • Comment on Text Analysis: given(){when(){}} block throws a 'useless use of private variable...etc' error
  • Select or Download Code

Replies are listed 'Best First'.
Re: Text Analysis: given(){when(){}} block throws a 'useless use of private variable...etc' error
by TomDLux (Vicar) on Oct 18, 2010 at 13:56 UTC

    Do you suppose the backslash at the end of line 1 has anything to do with it?

    Update: There's a closing curly missing at the end of the main line, before the first subroutine. And what's the '+' after 'size2' in the declaration line? That was caused by PerlMonks line-wrapping.

    update 2: SOLVED! given() takes a single variable or value, and assigns it to $_, so that in the various when() clauses, you can test $_ with various values / regex / routines. I'm quessing $_ is the private variable which is not used.

    You don't need to assign empty strings to the variables, nor do you need to compare against an empty string, undef or empty string are both 'false' in a boolean concept, that's a design feature, not an accident. Also, When reading a file, just read into a buffer variable, the read operation assigns undef to the buffer, ending the loop. I chomp the line when read, and skip empty lines, because I was getting an empty line at the end of the data file. Also, I use ||= to assign 'missed' to $snp if it doesn't have a string value.

    I'm not a biologist, but 'homo' means 'the same', 'hetero' means 'different'. So I'm thinking when allele1 and allele2 are both set, it should be 'homo', and 'hetero' should apply when only one is set.

    while ( my $line = <FH> ) { chomp $line; next unless length $line; my ( $file, $patientName, $panel, $snp, $allele1, $allele2, $size1 +, $size2 ) = split "\t", $line; $snp ||= 'missed'; if ( $allele1 && $allele2 ) { constructHetero( $snp, $patientName, $allele1, $allele2 ) } elsif ( $allele1 && not $allele2 ) { constructHomo( 'type1', $snp, $patientName, 'allele1', $allele +1 ) } elsif ( not $allele1 && $allele2 ) { constructHomo( 'type2', $snp, $patientName, 'allele2', $allele +2 ) } elsif ( not $allele1 && not $allele2) { constructUnclassified( $snp, $patientName ) } }

    update 3 : Changed from '!' to 'not' for negation, better visibility.

    As Occam said: Entia non sunt multiplicanda praeter necessitatem.

      I don't suppose so for the following reasons:
      1. The code is a boil down from a larger code that displayed the same behavior.
      2. The Perl path at the top of this line doesn't really matter here because I am using an editor on an XP machine so the path in the first line isn't really looked into upon compiling.
      The +s you see are because of a line overlap, if you hit on the download button at the left bottom of the code area you can have the entire code displayed without these +s..

      UPDATE: added the missing curly and removed the backslash pointed out, that should've been a pasting mistake of my code snippet, other than that, this code works and does show the behavior mentioned in the original post


      Excellence is an Endeavor of Persistence. A Year-Old Monk :D .
      You provided some very interesting clues to inspire me
      I'm quessing $_ is the private variable which is not used.
      If given takes a single variable or value and yet quite interesting still, it actually works with two values, even with three values as I tried it in the following demo, that means it is a very strong function that we probably need to develop more for us to avail of its full capacity in Perl 5.

      Thinking about if we can have an embedded given(){when(){}} to make it accept two arguments is out of the question since that may lead to a labyrinth of brain-damaging curlies but maybe just keeping track of the arguments passed to given in @_ may provide a path to beat if that can be possible...

      use strict; use warnings; use feature qw(switch); my $foo = 'foo'; my $bar = 'bar'; my $baz = 'baz'; given($foo, $bar, $baz){ when($foo eq 'check' and $bar eq 'treck'){print "nei +ther is standard\n";} when($foo eq 'foo' and $bar eq 'treck'){print "$foo +is standard\n";} when($foo eq 'check' and $bar eq 'bar'){print "$bar +is standard\n";} when($foo eq 'foo' and $bar eq 'bar' and $baz eq 'ba +z'){print "All are standard\n";} when($foo eq 'foo' and $bar eq 'bar'){print "both ar +e standard\n";} }
      Notice that the last 2 when blocks are both true however, the first one in order which evaluates to true is the one that gets its print statement executed and the second one is totally ignored, perambulation of the when blocks can testify to that...

      The reason I used a switch statement is because I wanted to clean up my code from the if else pollution in a quick way and the switch is a very neat way to do so, also, the values assigned to '' are going to be needed in another extension to the original code ergo the $var ||= '' statement.

      Checking perlsyn for clues..


      Excellence is an Endeavor of Persistence. A Year-Old Monk :D .

        In my opinion, you're abusing the "given/when" construct. Yes, it works, because you have a boolean expression in the when() clauses. But you could put anything in the given part, and it would work just the same.

        The point of "given/when", is that the value in the given clause is assigned to $_, and then you can use invisible default $_ in all the when() tests. From "perldoc perlsyn":

        given($_) { when (/^abc/) { $abc = 1; } when (/^def/) { $def = 1; } when (/^xyz/) { $xyz = 1; } default { $nothing = 1; } } # and similarly given($foo) { when (undef) { say '$foo is undefined'; } when ("foo") { say '$foo is the string "foo"'; } when ([1,3,5,7,9]) { say '$foo is an odd digit'; continue; # Fall through } when ($_ < 100) { say '$foo is numerically less than 100'; } when (\&complicated_check) { say 'a complicated check for $foo is true'; } default { die q(I don't know what to do with $foo); } }

        As far as I can see, you're using a given/when block to produce an if/elsif block with an extra level of indentation.

        If you modify your foo/bar/baz example so that each print block has a new statement after it: pritn "\$_ is $_.\n";. That will print out what the value of $_ is, no matter which path you take. You will see that $_ is 'baz'. Your ($foo, $bar, $baz) evaluates the sequence of expressions and uses the last one as the chosen value. The earlier ones are evaluated only for their side-effect. Of course, $foo does not have a side-effect, but it could equally be $foo++, or $foo->(). That's why you're getting the message about "useless use of a private variable", because only the last one gets assigned to $_.

        As Occam said: Entia non sunt multiplicanda praeter necessitatem.

Re: Text Analysis: given(){when(){}} block throws a 'useless use of private variable...etc' error
by AnomalousMonk (Archbishop) on Oct 18, 2010 at 17:25 UTC
    >perl -wMstrict -lE "my ($foo, $bar) = qw(FOO BAR); given ($foo) { when ($foo eq 'FOO') { print 'got a FOO'; } } " got a FOO >perl -wMstrict -lE "my ($foo, $bar) = qw(FOO BAR); given ($foo, $bar) { when ($foo eq 'FOO') { print 'got a FOO'; } } " Useless use of private variable in void context at... got a FOO

    See Switch statements in perlsyn.

Re: Text Analysis: given(){when(){}} block throws a 'useless use of private variable...etc' error
by kcott (Archbishop) on Oct 18, 2010 at 14:19 UTC

    I can't see a backslash at the end of line 1 nor a + after size (mentioned above by TomDLux) - perhaps the code was updated. I just see: $size1, $size2

    Missing } to close the until (also by TomDLux) is correct (i.e. I can see that one).

    Also, the semicolon at the end of sub constructHetero{...}; should be removed.

    -- Ken

Log In?
Username:
Password:

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

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

    No recent polls found