in reply to Re^3: reset particular variable
in thread reset particular variable

If you have a subroutine and you want to return "nothing" ...
But my questions in Re^2: reset particular variable were in the context of a discussion of differences between the  $var = (); and  $var = undef; et al statements, differences I still don't see.

WRT the examples you give in Re^3: reset particular variable, I realize now that what you mean by 'nothing' is 'an empty list'. I see the difference between returning an empty list and returning a list consisting of a single item that is undef (an undefined something).

Also WRT Re^3: reset particular variable, you say In Perl you can't even just exit a sub. But if you do an explicit  return; from a subroutine as opposed to an implicit return (i.e., falling off the end of the subroutine), then isn't the value returned always perfectly 'defined' semantically, dependent on the calling context of the subroutine? See examples below.

Other than documentary emphasis, is there any reason to prefer any of the other alternatves given below over a simple  return; statement? (Actually, I seem to recall that there exists an obscure case in which  return; and  return (); differ materially, but I don't have time right now to follow it up.)

>perl -wMstrict -le "sub Sr { return } sub Se { return () } sub Sw { return wantarray ? () : undef } print q{'}, Sr, q{' '}, join(q{' '}, 0+Sr, ''.Sr), q{'}; print q{'}, Se, q{' '}, join(q{' '}, 0+Se, ''.Se), q{'}; print q{'}, Sw, q{' '}, join(q{' '}, 0+Sw, ''.Sw), q{'}; " Use of uninitialized value in addition (+) at -e line 1. Use of uninitialized value in concatenation (.) or string ... '' '0' '' Use of uninitialized value in addition (+) at -e line 1. Use of uninitialized value in concatenation (.) or string ... '' '0' '' Use of uninitialized value in addition (+) at -e line 1. Use of uninitialized value in concatenation (.) or string ... '' '0' ''

Replies are listed 'Best First'.
Re^5: reset particular variable
by Marshall (Canon) on Aug 21, 2009 at 13:42 UTC
    Actually, I seem to recall that there exists an obscure case in which return; and return (); differ materially..

    Yes, Perl "bare return" does things that might not be expected. Basically, I figure it is a bad idea to use a "bare" "return;" and I just don't do it. The below code is a simple demo... "return" will return something unless you tell it to return "nothing". As I mentioned before, "returning nothing" is useful in map{}, but for a normal function, I would return "undef".

    #!/usr/bin/perl -w use strict; sub x { my $a =5; } print x; #prints 5
    Update: This part was wrong...goof in my testing! got a bit confused while doing this quickly...Oooops...I'll have to look at some other code I did awhile ago to find a better example...I think I have one somewhere. Anyway the idea of returning $x or () from within map{} is right idea to "skip" a value in output list.
    sub x1 { my $a =5; return; } print x1; #still prints 5! Whoa! #"return'" returns value of last true statement. #if you don't specify something else for it to return.
    sub x2 { my $a =5; return (); } print "x2:",x2; #prints "x2:" , ie nothing from sub x2
    Update: I don't see any basic disagreement or argument, but perhaps a misunderstanding of the application for this:

    But my questions in Re^2: reset particular variable were in the context of a discussion of differences between the $var = (); and $var = undef; et al statements, differences I still don't see.

    @outputlist = map{..code...}@inputlist;
    If I can "skip a value", instead of returning "undef" from the map, then say @outputlist could have fewer items in the list than @inputlist. Later when @outputlist is processed, there doesn't have to be code that says "check for undefined value", because there won't be any.
      Sorry marshall, but you're confusing explicit return with implicit return, ie. x1 doesn't still print 5
      sub fo { 5 } # implicit_return sub fox { 5; return } # explicit return print fo; print fox; __END__ 5
      perldoc -f return
        aside from the fact that your code doesn't work under -w and strict, your point is valid. I have amended my post above. Something is not right with my example. Well, stuff happens. Thanks for pointing this out!

      (I've seen Marshall's updated post, so this post is a bit redundant; but what the heck, I've already done the work, may as well cash the check.)

      Based on the example code below, I'm willing to go out on a limb and say there is no difference between the behavior of the  return; and  return (); statements in list or in scalar context; that is, although they behave differently in list versus scalar context, they behave differently in exactly the same way. (The example code uses the  $x = 1 + scalar @_; business to try to make absolutely sure that the 'statement evaluating to true' is not just optimized away by the compiler.)

      >perl -wMstrict -le "my $x; sub Sbr { $x = 1 + scalar @_; return } sub Sel { $x = 1 + scalar @_; return () } my ($s, @ra); $s = Sbr(); print 'scalar bare return ', defined $s ? '' : 'UN', 'defined'; print qq{scalar context bare return: '$s'}; $s = Sel(); print 'scalar empty list ', defined $s ? '' : 'UN', 'defined'; print qq{scalar context empty list: '$s'}; @ra = Sbr(); print qq{list context bare return: (@ra)}; @ra = Sel(); print qq{list context empty list: (@ra)}; " scalar bare return UNdefined Use of uninitialized value in concatenation (.) or string at ... scalar context bare return: '' scalar empty list UNdefined Use of uninitialized value in concatenation (.) or string at ... scalar context empty list: '' list context bare return: () list context empty list: ()

      So I guess it comes down to the questions: Is there any difference in the behavior of the  return; and  return(); and  return (); statements that does not arise from a context difference? Do they behave exactly the same way in list context? Do they behave exactly the same way in scalar context? My answers would be: no; yes; yes.

      (And BTW: I completely agree with you about the importance of returning an empty list in, e.g., a  map statement in which you wish to truncate the output list.)

        I suspect that you are right. I will have to "noodle on this a bit" to completely convince myself, but I suspect that it is true.

        As often happens in these threads, we have gone a long way from the original question about "reset"! I believe that there is consensus that package scoped variables and reset is not the best way although this is part of the language. I was surprised, but this IS truly a language construct. However, just because "it works", doesn't mean that it is a good idea - smaller scoped lexical variables is the "right" idea. Then we got onto map{} and how to suppress an "undef" value which is also a good idea.

        Now we are onto something that hasn't come up in the last few years of my coding. Almost all my subs{} return something and that result is expected and used or I consider this a coding error. Subs that don't return things are signal handlers or subs that modify a reference that is passed in. Basically I don't try to check return values from subs that aren't expected to return anything as a lvalue and I don't have much experience checking for this situation in a normal sub.

        I figure that until proved otherwise AnomalousMonk has it right! Great work! Thanks!