[Bioperl-l] get_nof_contigs returns undef
Heikki Lehvaslaiho
heikki.lehvaslaiho at gmail.com
Sat Sep 24 05:11:45 EDT 2005
So the question is how to force list context for a subroutine. This is
something I've often wondered and have not found a clean solution.
See optional ways to do this within George's function one():
sub one {
# option 0
# does not work, because sort() in moose() is defined in scalar context
return scalar( moose() );
# option 1
# does not work, shame because it would be most terse!
# is there a way to do this?
#return scalar( @{moose()} );
# option 2
# most common, but sort of stupid because it involves a variable
my @junk = moose();
return scalar( @junk);
#option 3
# performance issues?
return scalar( map {$_} moose() );
#option 4
# we are quickly running out of perl functions
# that work in list context...
return scalar( grep {/./} moose() );
}
-Heikki
On Friday 23 September 2005 22:50, George Hartzell wrote:
> Wes Barris writes:
> > [...]
> > I don't know enough about scalars and array refs to explain this, but
> > a fix for the above problem is:
> >
> > Old Bio/Assembly/Scaffold.pm code:
> >
> > sub get_nof_contigs {
> > my $self = shift;
> > return scalar( $self->get_contig_ids() );
> > }
> >
> > New Bio/Assembly/Scaffold.pm code:
> >
> > sub get_nof_contigs {
> > my $self = shift;
> > my @junk = $self->get_contig_ids;
> > return scalar( @junk );
> > # return scalar( $self->get_contig_ids() );
> > }
>
> Ouch. That makes my head hurt.
>
> I think that the answer's not about "scalars and array ref", but
> what happens when you evaluate things _in a scalar context_, and just
> when that occurs.
>
> Consider the following ridiculous piece of code.
>
> #!/usr/local/bin/perl -w
>
> use strict;
> use warnings;
>
> print "Without junk: ", one(), "\n";
> print "With junk: ", two(), "\n";
>
> sub one {
> return scalar( moose() );
> }
>
> sub two {
> my @junk = moose();
> return scalar( @junk);
> }
>
> sub moose {
> my $hash_ref = {};
>
> $hash_ref->{a} = 'a';
> $hash_ref->{b} = 'b';
> $hash_ref->{c} = 'c';
>
> return sort keys %{$hash_ref};
> }
>
> sub poodle {
> my $hash_ref = {};
>
> $hash_ref->{a} = 'a';
> $hash_ref->{b} = 'b';
> $hash_ref->{c} = 'c';
>
> if (wantarray()) {
> return sort keys %{$hash_ref};
> }
> else {
> return scalar(sort keys %{$hash_ref});
> }
> }
>
> sub ape {
> my $hash_ref = {};
>
> $hash_ref->{a} = 'a';
> $hash_ref->{b} = 'b';
> $hash_ref->{c} = 'c';
>
> if (wantarray()) {
> return sort keys %{$hash_ref};
> }
> else {
> return scalar(keys %{$hash_ref});
> }
> }
>
> Fire it up in the perl debugger and set a breakpoint in ape (in other
> words, 'b ape').
>
> Now call ape (in other words 'x ape');
>
> Now you should be sitting at the beginning of ape. Call wantarray by
> hand (in other words 'x wantarray'). **Lesson learned, the perl
> debugger evaluates function calls in a list context** (yeah, it does
> actually say that in the perldebug man page, but who reads *that*?).
> Now step the rest of the way through ape (or just continue, aka 'c')
> and you should see that it prints out the three items in the list
> (a,b,c).
>
> Quit the debugger and restart it on the same file (let's start fresh,
> or just delete the breakpoint you set above).
>
> This time do an 'x $a = ape' (since you're assigning the result of
> calling ape to a scalar variable, it forces it to be evaluated in a
> scalar context et voila, it returns 3.
>
> Now repeat the exercise with sub poodle{} and you'll see that it
> returns the list that you'd expect when you call it in an array
> context, but returns undef when you call it in a scalar context.
>
> Why?
>
> Here's where I'd love a comment from a Perl Language Lawyer, but my
> understanding of what's going on is that you're evaluating the sort()
> function in a scalar context, which Just Doesn't Work. sort's not set
> up to handle being called in a scalar context and you end up with
> undef.
>
> A less wind-baggy experiment would be to hop into the debugger and
> repeat this it makes sense:
>
> DB<20> x sort (1, 2, 3)
> 0 1
> 1 2
> 2 3
> DB<21> x scalar sort (1, 2, 3)
> 0 undef
> DB<22>
>
>
> Or, to be really brief about it, go look at "perldoc -f sort", where
> the first thing it says is:
>
> In list context, this sorts the LIST and returns the sorted
> list value. In scalar context, the behaviour of "sort()" is
> undefined.
>
> Then look at the output of "perldoc -f scalar" which starts off with:
>
> scalar EXPR
> Forces EXPR to be interpreted in scalar context and returns the
> value of EXPR.
>
> Probably should-a done that before....
>
> I'll happily buy a beer for the first person who I see *in person* who
> says: "You owe me a beer for making read all of that...".
>
> g.
> _______________________________________________
> Bioperl-l mailing list
> Bioperl-l at portal.open-bio.org
> http://portal.open-bio.org/mailman/listinfo/bioperl-l
--
______ _/ _/_____________________________________________________
_/ _/ http://www.ebi.ac.uk/mutations/
_/ _/ _/ Heikki Lehvaslaiho heikki at_ebi _ac _uk
_/_/_/_/_/ EMBL Outstation, European Bioinformatics Institute
_/ _/ _/ Wellcome Trust Genome Campus, Hinxton
_/ _/ _/ Cambridge, CB10 1SD, United Kingdom
_/ Phone: +44 (0)1223 494 644 FAX: +44 (0)1223 494 468
___ _/_/_/_/_/________________________________________________________
More information about the Bioperl-l
mailing list