Re: sub returning undef
by BrowserUk (Patriarch) on May 24, 2004 at 14:38 UTC
|
Have your sub return the empty list return (); or even (someways better) just return; for the error case. Then your array will be empty.
undef is a value. For example, my @array = (undef) x 5; print scalar @array; will print 5.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
| [reply] [d/l] [select] |
Re: sub returning undef
by Abigail-II (Bishop) on May 24, 2004 at 15:01 UTC
|
sub never return arrays. They return lists. If you do
return undef a list of one element is returned. If you assign that to a scalar, the scalar will have the undefined value. If you assign it to an array, you get an array with one element, that element being undef. It's not any different from return "feebleprops".
What is special cased is return;, that is, a return without arguments. In scalar context, that will return an undefined value - in list context, it will return an empty list. This is done especially to help in cases you are using.
Abigail | [reply] |
|
sub never return arrays. They return lists.
A sub never returns an array _directly_, but it can
return arrays by reference, along with anything else
it wants to return, in its list of return values.
The OP may have meant that the sub returns a list
of whatevers, or he might have meant that it returns
an array reference. It's hard to be certain since
he only gave us a possibly-misleading comment for
that case and focused on the error case where he
returns undef. My guess is, he hasn't _written_
the non-error case yet and hasn't put a lot of
thought into how it returns, but that's only a guess.
;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print
| [reply] |
|
| [reply] |
'use strict', debugger, Data::Dumper
by TomDLux (Vicar) on May 24, 2004 at 14:43 UTC
|
WhenI looked at your code, I wondered that you didn't have parentheses when you call mysub1, but it slipped past me all the same, until I did what you should have done, run the code in the debugger.
&mysub2(mysub1) invokes mysub2 with the text 'mysub1'; so @array is not empy.
If you used
use strict;
as you should, you would have been provided the warning
Bareword "mysub1" not allowed while "strict subs" in use at <file, lin
+e number>
Even without that warning, if you're confused that mysub2() is following the wrong path, the obvious thing to do is to find out what @array DOES contain, since it doesn't contain what you expect it to. You could print out what @_ contains at the routine entrty point, in which situation Data::Dumper is your friend.
use Data::Dumper;
sub mysub2 {
print STDERR Dumper( \@_ ), "\n";
my @array = @_;
will let you see things are not as you thought.
Or you could use your debugger. I prefer debugging from emacs (M-x perldb) but not everyone wants to spend the time to learn to use emacs. So use perl -d myscript, then type a letter 's' to 'single-step' into the mysub1() routine. "WOW! What are we doing in mysub2()?". Seeing the code elsewhere than you expected does a lot to guide your debugging ... :-)
--
TTTATCGGTCGTTATATAGATGTTTGCA
| [reply] [d/l] [select] |
Re: sub returning undef
by Stevie-O (Friar) on May 24, 2004 at 14:36 UTC
|
One problem I see is that 'undef' is an array of one element.
You should return an empty list: (). That will be treated as false by all conditionals (if unless while until).
--Stevie-O
$"=$,,$_=q>|\p4<6 8p<M/_|<('=>
.q>.<4-KI<l|2$<6%s!<qn#F<>;$,
.=pack'N*',"@{[unpack'C*',$_]
}"for split/</;$_=$,,y[A-Z a-z]
{}cd;print lc
| [reply] [d/l] [select] |
|
| [reply] |
|
eval {
# calls go here
};
if ($@) {
# exception handling here
}
| [reply] [d/l] |
|
|
Re: sub returning undef
by Happy-the-monk (Canon) on May 24, 2004 at 14:38 UTC
|
my @array = @_;
There's your array, even if $array[0] yields undef, @array still is a defined array with one single element.
Test for $_[0] being undef, before you create another array.
| [reply] |
Re: sub returning undef
by hardburn (Abbot) on May 24, 2004 at 14:41 UTC
|
Your code depends completely on how mysub2 is called. If you pass an argument, then mysub2 will show the array being defined. Remember that $foo->mysub2 does pass an argument.
----
send money to your kernel via the boot loader.. This and more wisdom available from Markov Hardburn.
| [reply] [d/l] [select] |
Re: sub returning undef
by adamk (Chaplain) on May 24, 2004 at 18:53 UTC
|
Perl is filled with people offering the best way to do things, often correctly, and sometimes totally not what you expect.
But since variety is the spice of life...
There are three reasonably cohesive ways to return a list, depending on what you are doing one of them should be relevant.
Return normally as a list
The original way is to return the data as a list (returning an array does this), and for the error case just 'return', gives you 'false' in both list and scalar context, the null array in the case of a list context, and undef in scalar context. This is the simplest, but when you want to also signal an error, suffers from tricky testing. In list form, () == error, which can suck when you legally return a null array. In scalar context, well... you only get the number anyways and not the list
You also get similar problems when you 'return undef', as undef returns in list context as a single element array with an undef in it, which is probably not what you REALLY want anyways. And what if a single undef element is a legal return value?
Exceptions
Secondly, we get the exception method, which in perl is essentially "die"ing with the error message. You might use formal exceptions, but they just die underneath. Very clean as you don't have to test for errors everywhere, but if you don't want to be eval/try'ing all the time, or the 'policy' for the code doesn't not allow to use exceptions everywhere, this can get nasty.
Return by reference
My personal favourite, and I suspect the best answer in this situation, return just return the list by reference.
&mysub2(mysub1);
sub mysub1{
# Returning something
return \@data;
# on error
return undef;
}
sub mysub2{
my $result = @_;
unless($result){
print "Array is not defined" #Expected out come
}else{
print "Exists";
}
}
You can then continue as normal.
I actually do something else, where I return defined but false for a null list, which can come in handy for something like
my $rv = getsomething();
die "Error while getting something" unless defined $rv;
die "We did not find anything" unless $rv;
print "Found " . scalar(@$rv) . " thing(s)\n";
Anyway, I suspect that's something like what you want.
Of course, if you DON'T return an error, I prefer to just return as a list.
For suggestions on a comprehensive return value policy that effectively covers all possible combinations of return value and error(or not), you might like to see http://ali.as/devel/code.html#6, part of my code style policy for myself and my company. | [reply] [d/l] [select] |
|
I have a question on that notion of returning the list by reference. Would that get you into trouble, if the list you were trying to return were in a variable local to the routine doing the returning? In that case, you're providing a reference to something that is about to wink out of existence, right? Or do I misunderstand what you're saying or how it works? (I don't mean to brag, but my ignorance is vast.)
| [reply] |
|
Well, in the 'local' sense of local, I'm not sure. You should be using the 'local' keyword only to temporarily overload some global variable ( mainly anyway ).
In the 'my' sense, which is really 'lexical' I believe, no.
By returning by reference, you've added a second reference to the same data. The original dissapears, leaving you with 1 again. The data won't be nuked until you get to zero references to the data.
| [reply] |
|
Re: sub returning undef
by qq (Hermit) on May 24, 2004 at 22:28 UTC
|
I have a sub which if all goes well returns an array but if a error is encounted returns undef. I belived this to be good style and know that many built in functions do this.
Abigail-II provided the answer, but its getting a bit obscured. Its not good style to return undef because if its assigned to an array you get a one element list. Its better style to just return. Because that is shorthand for:
wantarray ? () : undef;
Which is what you almost always want
qq
| [reply] [d/l] [select] |
|
Unless of course the method can legally return a null list, in which case it isn't :)
| [reply] |
Re: sub returning undef
by jonadab (Parson) on May 24, 2004 at 15:16 UTC
|
my @array = @_;
What do you mean, exactly, when you say that mysub1
returns an array? If it returns an anonymous array,
then the assignment above should read something like
my @array = @{shift@_};
As it stands
now, not only does the code not do what you want in
the error case, it won't do what you want in the
case where an array is returned either.
;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print
| [reply] [d/l] [select] |
Re: sub returning undef
by orderthruchaos (Scribe) on May 24, 2004 at 17:50 UTC
|
| [reply] [d/l] [select] |
Re: sub returning undef
by tilly (Archbishop) on May 25, 2004 at 15:13 UTC
|
Which built-in functions return arrays but return undef on error?
I both would not recommend that style, and strongly suspect that you're misunderstanding something basic about the behaviour of those functions. | [reply] |