in reply to Re^2: Perl Style: Is initializing variables considered taboo?
in thread Perl Style: Is initializing variables considered taboo?

there are cases where assigning undef makes sense but generally it's a waste of time (which is not Perl style ;)

Applications are especially when passing "positional" lists or assigning to lists, with "gaps".

i.e.

($a,undef,$b)=@array; # ignore second parameter
or
function($a,undef,$b) {..} # treat second parameter as not suppl +ied

The latter is especially necessary if you are checking arguments within the sub for definedness and changing to default values.

UPDATE: An extension of this case is a hash or array element which exists but is not defined!

> Of course I use strictures in all my code!

it's more about use warnings to be warned about undefined variables.

UPDATE:

and please be careful not to return undef to "explicitly" return false.

Subs return lists, so what you are actually doing is returning a one-element list instead of an empty one. I.e. @array=func();

Using a blank return is the same like return (); and won't byte you in list context but in scalar context the variable will be undef anyway.

Cheers Rolf

Replies are listed 'Best First'.
Re^4: Perl Style: Is initializing variables considered taboo?
by TomDLux (Vicar) on Aug 22, 2010 at 01:49 UTC
    If I need to discard a value from an array or from a list of return values, I usually index the list, rather than assign values into undef.
    ($a, $b)= @array[1,3]; my ($minutes, $hours) = (localtime())[2,3]
    Though the localtime example is artificial, I rarely do anything with list-context localtime(), anymore, other than feed it into Posix::strftime().

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re^4: Perl Style: Is initializing variables considered taboo?
by ait (Hermit) on Aug 22, 2010 at 16:47 UTC
    and please be careful not to return undef to "explicitly" return false.
    Many people use return undef to indicate false in the execution of a sub, but it's likely I'm really not getting what you mean by "explicitly":
    perl -e 'foreach (@INC){print "$_\n" unless $_ eq q{.}}' | xargs grep +-R "return undef" | wc -l<br> 1752
    Subs return lists, so what you are actually doing is returning a one-element list instead of an empty one. I.e. @array=func(); Using a blank return is the same like return (); and won't byte you in list context but in scalar context the variable will be undef anyway.
    I have found it wise to always return an explicit value, to avoid a potential bite or 'feature' of the "last expression", and have till now, used undef to indicate falseness and failure, and a defined value or "1", to indicate trueness/success.

    As you point out, it is often overlooked that Perl returns lists and as a result most of the time subs are evaluated in scalar context; in OO code it's customary to return a single ref to an object or undef on failure. So what exactly do you mean by not returning undef to "explicitly" return false.

      In scalar context, return; evaluates to undef. In list context, it evaluates to the empty list. In both contexts, it evaluates to something which evaluates to false in boolean context.

      In list context, return undef; evaluates to a single-element list which evaluates to true in boolean context.

      > So what exactly do you mean by not returning undef to "explicitly" return false.

      maybe a little example will make it clearer

      DB<1> sub tst {return undef} DB<2> if ($a=tst()) {print "TRUE"} else {print "FALSE" } FALSE DB<3> if (@a=tst()) {print "TRUE"} else {print "FALSE" } TRUE DB<4> sub tst { return (); } DB<5> if ($a=tst()) {print "TRUE"} else {print "FALSE" } FALSE DB<6> if (@a=tst()) {print "TRUE"} else {print "FALSE" } FALSE

      line 4 is of course redundant, return; and  return (); do exactly the same thing.

      > I have found it wise to always return an explicit value,

      OK, if you wanna code more "explicitly", you should better define constants for TRUE, FALSE and FAILED.

      DB<9> use constant FAILED => (); DB<10> use constant FALSE => !1; DB<11> use constant TRUE => 1; DB<12> sub t_FALSE { return FALSE; } DB<13> sub t_TRUE { return TRUE; } DB<14> sub t_FAILED { return FAILED; } DB<15> if (@a=t_FAILED) {print "TRUE"} else {print "FALSE" } FALSE DB<16> if (@a=t_FALSE) {print "TRUE"} else {print "FALSE" } TRUE DB<17> if ($a=t_FALSE) {print "TRUE"} else {print "FALSE" } FALSE DB<18> if ($a=t_FAILED) {print "TRUE"} else {print "FALSE" } FALSE

      If you wonder about my definition of FALSE, see Truth and Falsehood in perlsyn:

      Negation of a true value by "!" or "not" returns a special fals +e value. When evaluated as a string it is treated as '', but as a number +, it is treated as 0.

      UPDATE:

      please note: FALSE is defined!

      DB<27> p !defined (FAILED) 1 DB<28> p defined (FALSE) 1

      i.e. FALSE acts like a defined value like in most other languages.

      UPDATE:

      On second thought FAILED should better be named EMPTY or NOTHING. Failure is just an interpretation of returning nothing.

      Cheers Rolf

        If you wonder about my definition of FALSE, see Truth and Falsehood in perlsyn:

        From the pod you are reffering to:

        The number 0, the strings '0' and '' , the empty list () , and undef are all false in a boolean context. All other values are true. Negation of a true value by ! or not returns a special false value. When evaluated as a string it is treated as '' , but as a number, it is treated as 0.

        I still believe it's more customary to use undef as the ultimate null and false value in Perl. For example in DBI, DBIx::Class and alike, if you set a field to undef it will store in the database as an actual NULL whereas if you use '' (the empty string) you will get a blank string in the database, probably not what you'd want. I have a feeling that the explicit returning of undef is a quite popular convention :)

        This "ultimate null/false discussion" is probably steering OT and should move to a new thread IMO, though I would suspect that it has been discussed ad nauseam here in PM.