Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

sub that sets $_

by holli (Abbot)
on Jun 28, 2005 at 10:35 UTC ( [id://470565]=perlquestion: print w/replies, xml ) Need Help??

holli has asked for the wisdom of the Perl Monks concerning the following question:

Monks, in Re: Handling A File In Human-Compatible Chunks i proposed a module that can be used like
#iterate while ( my $chunk = $reader->chunk ) { print "$chunk\n****************\n"; }
That works, but this
#iterate while ( $reader->chunk ) { print "$_\n****************\n"; }
does not. $_ is not set. How can I achieve that behaviour?

Tx.

Replies are listed 'Best First'.
Re: sub that sets $_
by tlm (Prior) on Jun 28, 2005 at 10:39 UTC

    In a while expression, the automatic setting of $_ happens only when the content of the parentheses after the while is an expression of the form <HANDLE>. You'll need something like

    while ( $_ = $reader->chunk ) {

    the lowliest monk

      Don't forget to use local $_ before while ( $_ = $reader->chunk ) {, or you might clobber something without even realizing it. For example, the following snippet replaces the content of @array with false values because $_ is (in turn) a reference to each element of @array:

      foreach (@array) { ... my $reader = ...; ... while ($_ = $reader->chunk) { ... } ... }

      The following dies with the run-time error "Modification of a read-only value attempted":

      for ('a', 'b') { ... my $reader = ...; ... while ($_ = $reader->chunk) { ... } ... }

        Yes. Actually, nobull recently made the case for localizing *_ instead of $_, although this added precaution is probably more important for functions and methods in modules than for top-level code.

        the lowliest monk

      Well, that circumvents the whole convenience. Sad. I believed that would be possible.

      Thanks for your response.
        Well, it may be possible with a tied hash. Would it be worth, though? (except for fun, that is - I've never played with this "kinda things" myself, but I'm tempted!)

        UPDATE:as per revdiablo's remark, s/hash/filehandle/. Just a typo, and only because tied hashes are IMHO the kind of tied objects one most often can hear about...

Re: sub that sets $_
by TheDamian (Vicar) on Jun 28, 2005 at 11:52 UTC
    It is possible to do what you want...by returning an object. See the implementation of IO::Prompt for an example.

      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. :-(

        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>?)

Re: sub that sets $_
by monarch (Priest) on Jun 28, 2005 at 11:01 UTC
    Can you somehow tie $reader->chuck to return a file handle?
Re: sub that sets $_
by anonymized user 468275 (Curate) on Jun 28, 2005 at 11:17 UTC
    ...by changeing the while into for?

    One world, one people

      That would mean I have to read the whole file into memory, and return a list of chunks. Depending on the filesize this might turn out as a bad idea ;-)
        No - each iteration returns a chunk into $_ in the for or foreach loop.

        One world, one people

      or foreach.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://470565]
Approved by marto
Front-paged by jbrugger
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-04-19 14:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found