Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

sub that sets $_

by holli (Monsignor)
on Jun 28, 2005 at 10:35 UTC ( #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.

Comment on sub that sets $_
Select or Download Code
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

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

      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

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 SimonClinch (Chaplain) on Jun 28, 2005 at 11:17 UTC
    ...by changeing the while into for?

    One world, one people

      or foreach.
      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

Re: sub that sets $_
by TheDamian (Priest) 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>?)

Log In?
Username:
Password:

What's my password?
Create A New User
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? | Other CB clients
Other Users?
Others perusing the Monastery: (20)
As of 2015-07-01 15:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (6 votes), past polls