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 | [reply] [d/l] |
|
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) {
...
}
...
}
| [reply] [d/l] [select] |
|
| [reply] |
|
Well, that circumvents the whole convenience. Sad. I believed that would be possible.
Thanks for your response.
| [reply] |
|
| [reply] |
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. | [reply] |
|
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
| [reply] [d/l] [select] |
|
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. :-(
| [reply] |
|
|
| [reply] |
|
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>?)
| [reply] [d/l] |
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? | [reply] |
Re: sub that sets $_
by anonymized user 468275 (Curate) on Jun 28, 2005 at 11:17 UTC
|
...by changeing the while into for?
| [reply] |
|
remember that for (LIST) localizes $_ and while (<HANDLE>) doesn't. Generally, for() is safer, but sometimes you want the while() behaviour.
| [reply] [d/l] [select] |
|
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 ;-)
| [reply] |
|
No - each iteration returns a chunk into $_ in the for or foreach loop.
| [reply] |
|
|
|
|
| [reply] [d/l] |