http://www.perlmonks.org?node_id=470586


in reply to sub that sets $_

It is possible to do what you want...by returning an object. See the implementation of IO::Prompt for an example.

Replies are listed 'Best First'.
Re^2: sub that sets $_
by Animator (Hermit) on Jun 28, 2005 at 12:08 UTC

    That's not quite correct...

    IO::Prompt returns an object, in that object bool is overloaded, and bool sets $_. (which is run for each iteration of the while to decided if it's a true or false value)

    Which means that while ($z = prompt "") { will set $_ and $z. This is a bad idea. What if the code is used in an inner loop? when the outer loop uses $_ for example?

    If one wants to get the same behaviour then it would be enough to do a simple assignment in the subroutine to $_ and return the value of $_.

    Example code that is similar to the code in IO::Prompt

    Update: added relevant part of IO::Prompt

      Which means that while ($z = prompt "") { will set $_ and $z. This is a bad idea. What if the code is used in an inner loop? when the outer loop uses $_ for example?
      Yes, that is a nuisance. I'm working on overcoming that problem, but it's difficult: Perl never quite gives you enough context information to detect the assignment. :-(
        On further investigation, it appears that you can tell the two contexts apart using the Want module. Specifically, want('BOOL') knows the difference. For example:
        my $flipflop = 0; sub foo { use Want qw(want); print 'not ' if !want 'BOOL'; print "bool\n"; return $flipflop=!$flipflop; # alternate true and false } for (1..3) { while (foo() ) { # print "here 1\n"; } while ($answer = foo() ) { # print "here 2\n"; } }

        Unfortunately, under 5.8.3 I get bus errors if there I uncomment the print statements, or if there is anything in the while blocks. :-(

Re^2: sub that sets $_
by holli (Abbot) on Jun 28, 2005 at 12:29 UTC

      First of all congratulations with the excelent idea to use DESTROY to set $_.

      Second, it still has a little bug though... it will set the value of $_ when the object gets destroyed... which is why it works and why it is bugged. Example:

      $_ = "abc"; { my $line = $reader->chunk(); } print $_;
      $_ won't have the value "abc"...

      Update: since I'm not that familiar with overloading I re-looked at the overload pod... (to see if there is a function that is always called, so that the DESTROY could be made conditional/optional). In it I found an intresting overload option.

      You can overload <>. This would mean that you can overload it in your main module and use <$reader>. Which will set the appropriate variable. (Using < $reader->chunk > is not possible since it is a syntax error. You could ofcourse assign it to a temp var and use that but what would be wrong with using <$reader>?)