Ask a Question related to PERL Beginners, Design and Development.
-
Sam #1
[Q] How to eval an EXPR once and make it stick
# Print lines (or not) until a blank line is found (or not)
# This function works fine. But in the spirit of learning...read on.
sub print_lines_ok {
my ($output, $blank_lines) = @_;
if ($blank_lines) {
do {
print if $output;
$_ = <>;
} while (/^\s*$/ and not eof);
} else {
do {
print if $output;
$_ = <>;
} while (not /^\s*$/ and not eof);
}
}
# This function is the same thing; just more 'elegant' IMHO. :-)
# But it has its problems. I can eval it in the while loop and it
# works as it is below, but it's painfully slow. I *know* there's no
# need for the eval call every iteration but so far haven't figured
# out how to use eval outside the while AND have it work. It
# appears $expr is always true unless the eval is done in the while loop.
# In summary, how can I build a dynamic regexp that I can eval once
# and then use?
sub print_lines_ideal {
my ($output, $blank_lines) = @_;
my $expr = $blank_lines ? '/^\s*$/' : 'not /^\s*$/';
# eval $expr # I want to eval this ONCE and then use it. Help?
do {
print if $output;
$_ = <>;
} while (eval $expr and not eof); # works, but not fast.
# Can I move eval out of loop?
}
__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free web site building tool. Try it!
[url]http://webhosting.yahoo.com/ps/sb/[/url]
Sam Guest
-
M'I`5 Perse cution Bern ard Levi n expr esses his views
The article of which part is reproduced below. was penned by Bernard Levin for. the Features section of the Times on 21 September 1991. To my mind,... -
#39835 [NEW]: Configure script fails with expr: syntax error
From: cheetah at tanabi dot org Operating system: Solaris 10 PHP version: 5.2.0 PHP Bug Type: *Compile Issues Bug... -
Inconsistent behaviour of empty "while" EXPR
Odd one this:an empty EXPRession in a "while" loop seems to take a defined value in this call from either ksh on solaris 2.6 to Perl 5.004, or... -
DECO_32.dll ...where do I stick it?
G'day In response to missing component error message (at P'shop 6 startup in win XPpro) I downloaded the missing component DECO_32.dll (as directed... -
Cleaning stick
Anyone know of a cleaning stick I saw on in 1 of the photo magazine. Outdoor photo. More info is needed before I buy on. Any help would be great... -
Rob Dixon #2
Re: [Q] How to eval an EXPR once and make it stick
Sam wrote:
I don't think you want what you've written, as the first call to 'print'>
> # Print lines (or not) until a blank line is found (or not)
>
> # This function works fine. But in the spirit of learning...read on.
>
> sub print_lines_ok {
>
> my ($output, $blank_lines) = @_;
>
> if ($blank_lines) {
> do {
> print if $output;
>
> $_ = <>;
>
> } while (/^\s*$/ and not eof);
> } else {
> do {
> print if $output;
>
> $_ = <>;
>
> } while (not /^\s*$/ and not eof);
> }
> }
>
>
> # This function is the same thing; just more 'elegant' IMHO. :-)
> # But it has its problems. I can eval it in the while loop and it
> # works as it is below, but it's painfully slow. I *know* there's no
> # need for the eval call every iteration but so far haven't figured
> # out how to use eval outside the while AND have it work. It
> # appears $expr is always true unless the eval is done in the while loop.
> # In summary, how can I build a dynamic regexp that I can eval once
> # and then use?
>
>
> sub print_lines_ideal {
>
> my ($output, $blank_lines) = @_;
> my $expr = $blank_lines ? '/^\s*$/' : 'not /^\s*$/';
>
> # eval $expr # I want to eval this ONCE and then use it. Help?
>
>
> do {
> print if $output;
>
> $_ = <>;
>
> } while (eval $expr and not eof); # works, but not fast.
> # Can I move eval out of loop?
> }
>
is before anything has been read from the file. This should come close:
sub print_lines {
my ($output, $blank_lines) = @_;
while (<>) {
last if $blank_lines xor /\S/;
print if $output;
}
}
Rob
Rob Dixon Guest
-
John W. Krahn #3
Re: [Q] How to eval an EXPR once and make it stick
Sam wrote:
You are printing the contents of $_ but you don't have anything in $_>
> # Print lines (or not) until a blank line is found (or not)
> # This function works fine. But in the spirit of learning...read on.
>
> sub print_lines_ok {
> my ($output, $blank_lines) = @_;
> if ($blank_lines) {
> do {
> print if $output;
until the next line.
Perhaps this is what you want:> $_ = <>;
> } while (/^\s*$/ and not eof);
> } else {
> do {
> print if $output;
> $_ = <>;
> } while (not /^\s*$/ and not eof);
> }
> }
>
> # This function is the same thing; just more 'elegant' IMHO. :-)
> # But it has its problems. I can eval it in the while loop and it
> # works as it is below, but it's painfully slow. I *know* there's no
> # need for the eval call every iteration but so far haven't figured
> # out how to use eval outside the while AND have it work. It
> # appears $expr is always true unless the eval is done in the while loop.
> # In summary, how can I build a dynamic regexp that I can eval once
> # and then use?
>
> sub print_lines_ideal {
> my ($output, $blank_lines) = @_;
> my $expr = $blank_lines ? '/^\s*$/' : 'not /^\s*$/';
> # eval $expr # I want to eval this ONCE and then use it. Help?
> do {
> print if $output;
> $_ = <>;
> } while (eval $expr and not eof); # works, but not fast.
> # Can I move eval out of loop?
> }
sub print_lines_ideal {
my ( $output, $blank_lines ) = @_;
my $expr = $blank_lines ? qr/^\s*$/ : qr/\S/;
while ( <> ) {
print if $output and /$expr/;
}
}
John
--
use Perl;
program
fulfillment
John W. Krahn Guest
-
Jeff 'Japhy' Pinyan #4
Re: [Q] How to eval an EXPR once and make it stick
On Jan 27, Rob Dixon said:
You could just say>Sam wrote:>>
>> sub print_lines_ok {
>> my ($output, $blank_lines) = @_;
>> if ($blank_lines) {
>> do {
>> print if $output;
>> $_ = <>;
>> } while (/^\s*$/ and not eof);
>> } else {
>> do {
>> print if $output;
>> $_ = <>;
>> } while (not /^\s*$/ and not eof);
>> }
>> }
>>
>>
>> sub print_lines_ideal {
>> my ($output, $blank_lines) = @_;
>> my $expr = $blank_lines ? '/^\s*$/' : 'not /^\s*$/';
>>
>> do {
>> print if $output;
>> $_ = <>;
>> } while (eval $expr and not eof); # works, but not fast.
>> # Can I move eval out of loop?
>> }
do ... while (($blank ? /^\s*$/ : not /^\s*$/) and not eof);
which could be written with 'xor' as Rob shows below:
do ... while ($blank xor not /^\s*$/) and not eof;
and 'not /^\s*$/' can be written as /\S/, which results in Rob's code.
That might work in this specific case, but if you want to be able to>I don't think you want what you've written, as the first call to 'print'
>is before anything has been read from the file. This should come close:
>
> sub print_lines {
> my ($output, $blank_lines) = @_;
> while (<>) {
> last if $blank_lines xor /\S/;
> print if $output;
> }
> }
change the course of events like that without constant re-evaluation, I'd
suggest using code references:
my $code = \&first;
sub first {
# code for the first case
if (some condition) { $code = \&second }
}
sub second {
# code for the second case
}
$code->();
--
Jeff "japhy" Pinyan [email]japhy@pobox.com[/email] [url]http://www.pobox.com/~japhy/[/url]
RPI Acacia brother #734 [url]http://www.perlmonks.org/[/url] [url]http://www.cpan.org/[/url]
<stu> what does y/// stand for? <tenderpuss> why, yansliterate of course.
[ I'm looking for programming work. If you like my work, let me know. ]
Jeff 'Japhy' Pinyan Guest
-
Rob Dixon #5
Re: [Q] How to eval an EXPR once and make it stick
John W. Krahn wrote:
Hi John.>
> Sam wrote:>> >
> > # Print lines (or not) until a blank line is found (or not)
> > # This function works fine. But in the spirit of learning...read on.
> >
> > sub print_lines_ok {
> > my ($output, $blank_lines) = @_;
> > if ($blank_lines) {
> > do {
> > print if $output;
> You are printing the contents of $_ but you don't have anything in $_
> until the next line.
>
>>> > $_ = <>;
> > } while (/^\s*$/ and not eof);
> > } else {
> > do {
> > print if $output;
> > $_ = <>;
> > } while (not /^\s*$/ and not eof);
> > }
> > }
> >
> > # This function is the same thing; just more 'elegant' IMHO. :-)
> > # But it has its problems. I can eval it in the while loop and it
> > # works as it is below, but it's painfully slow. I *know* there's no
> > # need for the eval call every iteration but so far haven't figured
> > # out how to use eval outside the while AND have it work. It
> > # appears $expr is always true unless the eval is done in the while loop.
> > # In summary, how can I build a dynamic regexp that I can eval once
> > # and then use?
> >
> > sub print_lines_ideal {
> > my ($output, $blank_lines) = @_;
> > my $expr = $blank_lines ? '/^\s*$/' : 'not /^\s*$/';
> > # eval $expr # I want to eval this ONCE and then use it. Help?
> > do {
> > print if $output;
> > $_ = <>;
> > } while (eval $expr and not eof); # works, but not fast.
> > # Can I move eval out of loop?
> > }
> Perhaps this is what you want:
>
> sub print_lines_ideal {
> my ( $output, $blank_lines ) = @_;
> my $expr = $blank_lines ? qr/^\s*$/ : qr/\S/;
> while ( <> ) {
> print if $output and /$expr/;
> }
> }
It's hard to be sure, as we're guessing what the required algorithm is; but
the original code dropped out at the /first/ line that failed the blank or
non-blank test. Your solution may need to be:
while ( <> ) {
last unless /$expr/;
print if $output;
}
which I must say looks rather neat :)
Rob
Rob Dixon Guest
-
Sam #6
Re: [Q] How to eval an EXPR once and make it stick
Thanks for all your responses; I learned a bit.
1. I wasn't clear on $_ in my email; that's being read elsewhere in program so
it's already set by the time print_lines is called.
2. Will you bet your life on this equivalence: "not /^\s*$/ == /\S/"? I
believe it's safer to negate an EXPR than to find some other EXPR2 that is
equivalent to 'not EXPR'.
3. Hadn't thought about xor; good to know.
4. As for the generalized case, I learned about using refs. Anonymous subs
also work.
my $re = sub { return /^\s*$/; };
my $nre = sub { return not &$re; };
my $expr = $blank ? $re : $nre;
do ... while (&$expr and not eof);
But I'm not sure which is faster though.
Thanks for all your help.
--- Jeff 'japhy' Pinyan <japhy@perlmonk.org> wrote:> On Jan 27, Rob Dixon said:
>>> >Sam wrote:> >>
> >> sub print_lines_ok {
> >> my ($output, $blank_lines) = @_;
> >> if ($blank_lines) {
> >> do {
> >> print if $output;
> >> $_ = <>;
> >> } while (/^\s*$/ and not eof);
> >> } else {
> >> do {
> >> print if $output;
> >> $_ = <>;
> >> } while (not /^\s*$/ and not eof);
> >> }
> >> }
> >>
> >>
> >> sub print_lines_ideal {
> >> my ($output, $blank_lines) = @_;
> >> my $expr = $blank_lines ? '/^\s*$/' : 'not /^\s*$/';
> >>
> >> do {
> >> print if $output;
> >> $_ = <>;
> >> } while (eval $expr and not eof); # works, but not fast.
> >> # Can I move eval out of loop?
> >> }
> You could just say
>
> do ... while (($blank ? /^\s*$/ : not /^\s*$/) and not eof);
>
> which could be written with 'xor' as Rob shows below:
>
> do ... while ($blank xor not /^\s*$/) and not eof;
>
> and 'not /^\s*$/' can be written as /\S/, which results in Rob's code.
>>> >I don't think you want what you've written, as the first call to 'print'
> >is before anything has been read from the file. This should come close:
> >
> > sub print_lines {
> > my ($output, $blank_lines) = @_;
> > while (<>) {
> > last if $blank_lines xor /\S/;
> > print if $output;
> > }
> > }
> That might work in this specific case, but if you want to be able to
> change the course of events like that without constant re-evaluation, I'd
> suggest using code references:
>
> my $code = \&first;
>
> sub first {
> # code for the first case
> if (some condition) { $code = \&second }
> }
>
> sub second {
> # code for the second case
> }
>
> $code->();
>
> --
> Jeff "japhy" Pinyan [email]japhy@pobox.com[/email] [url]http://www.pobox.com/~japhy/[/url]
> RPI Acacia brother #734 [url]http://www.perlmonks.org/[/url] [url]http://www.cpan.org/[/url]
> <stu> what does y/// stand for? <tenderpuss> why, yansliterate of course.
> [ I'm looking for programming work. If you like my work, let me know. ]
>
>
> --
> To unsubscribe, e-mail: [email]beginners-unsubscribe@perl.org[/email]
> For additional commands, e-mail: [email]beginners-help@perl.org[/email]
> <http://learn.perl.org/> <http://learn.perl.org/first-response>
>
>
__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free web site building tool. Try it!
[url]http://webhosting.yahoo.com/ps/sb/[/url]
Sam Guest
-
Rob Dixon #7
Re: [Q] How to eval an EXPR once and make it stick
Sam wrote:
Good: well done.>
> Thanks for all your responses; I learned a bit.
You /mustn't/ use $_ like that. It's meant to be an 'it' in places like> 1. I wasn't clear on $_ in my email; that's being read elsewhere in program so
> it's already set by the time print_lines is called.
For each banana, look at it, smell it, and eat it.
NOT
When I say 'it', it means 'banana 3 from crate 5'.
For each apple, look at it, smell it, and eat it.
Do it to it.
Yes. (But I can think of more valuable things to bet on.)> 2. Will you bet your life on this equivalence: "not /^\s*$/ == /\S/"? I
> believe it's safer to negate an EXPR than to find some other EXPR2 that is
> equivalent to 'not EXPR'.
The first says,
Does the entire string, from start to end, consist of zero or more 'space' characters?
The second says,
Does the string contain a non-'space' character anywhere?
The only difficulty could be with a zero-length string, which is still fine, if
you think about it.
Be careful though. 'xor' goes with the other low-precedence operators 'and'> 3. Hadn't thought about xor; good to know.
and 'or', which have the high-precedence equivalents && and ||. 'xor' has
no equivalent. (The caret, ^, is a bitwise operator, which is completely
different.)
Eek. Don't do that. It may work, but it's not at all obvious what $_ is in the> 4. As for the generalized case, I learned about using refs. Anonymous subs
> also work.
>
> my $re = sub { return /^\s*$/; };
> my $nre = sub { return not &$re; };
context of a subroutine call. Having $nre dereference $re at each call isn't
your best bet either.
The better syntax for a call to a subroutine reference is> my $expr = $blank ? $re : $nre;
> do ... while (&$expr and not eof);
$expr->()
which doesn't assume all sorts of things that could keep you awake at night if
you knew.
If you don't know, it doesn't matter.> But I'm not sure which is faster though.
If your software is /too/ slow and you would die for a 10% speed increase then
check out
use Benchmark;
If not, don't bother.
HTH,
Rob
Rob Dixon Guest
-
Sam #8
Re: [Q] How to eval an EXPR once and make it stick
--- Rob Dixon <rob@dixon.port995.com> wrote:What? You want me to pass the line around in a variable! :-)> Sam wrote:>> >
> > Thanks for all your responses; I learned a bit.
> Good: well done.
>> program so> > 1. I wasn't clear on $_ in my email; that's being read elsewhere in>> > it's already set by the time print_lines is called.
> You /mustn't/ use $_ like that. It's meant to be an 'it' in places like
I hear 'ya, but I like to avoid possible boundary conditions that make me think>
> For each banana, look at it, smell it, and eat it.
>
> NOT
>
> When I say 'it', it means 'banana 3 from crate 5'.
> For each apple, look at it, smell it, and eat it.
> Do it to it.
>>> > 2. Will you bet your life on this equivalence: "not /^\s*$/ == /\S/"? I
> > believe it's safer to negate an EXPR than to find some other EXPR2 that is
> > equivalent to 'not EXPR'.
> Yes. (But I can think of more valuable things to bet on.)
>
> The first says,
>
> Does the entire string, from start to end, consist of zero or more 'space'
> characters?
>
> The second says,
>
> Does the string contain a non-'space' character anywhere?
>
> The only difficulty could be with a zero-length string, which is still fine,
> if
> you think about it.
'what if.' Just using 'not' avoids that mess. In this case the re was simple
enough, but w/more complex ones...
Ok, that's good to know.>>> > 3. Hadn't thought about xor; good to know.
> Be careful though. 'xor' goes with the other low-precedence operators 'and'
> and 'or', which have the high-precedence equivalents && and ||. 'xor' has
> no equivalent. (The caret, ^, is a bitwise operator, which is completely
> different.)
>> subs> > 4. As for the generalized case, I learned about using refs. Anonymous>> > also work.
> >
> > my $re = sub { return /^\s*$/; };
> > my $nre = sub { return not &$re; };
> Eek. Don't do that. It may work, but it's not at all obvious what $_ is in
> the
> context of a subroutine call. Having $nre dereference $re at each call isn't
> your best bet either.
>>> > my $expr = $blank ? $re : $nre;
> > do ... while (&$expr and not eof);
> The better syntax for a call to a subroutine reference is
>
> $expr->()
>
> which doesn't assume all sorts of things that could keep you awake at night
> if
> you knew.
No it hums along fine. But using eval was *really* slow and clearly I was on>>> > But I'm not sure which is faster though.
> If you don't know, it doesn't matter.
>
> If your software is /too/ slow and you would die for a 10% speed increase
> then
> check out
>
> use Benchmark;
>
> If not, don't bother.
the wrong track using it.
Thanks.
>
> HTH,
>
> Rob
>
>
>
> --
> To unsubscribe, e-mail: [email]beginners-unsubscribe@perl.org[/email]
> For additional commands, e-mail: [email]beginners-help@perl.org[/email]
> <http://learn.perl.org/> <http://learn.perl.org/first-response>
>
>
__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free web site building tool. Try it!
[url]http://webhosting.yahoo.com/ps/sb/[/url]
Sam Guest
-
John W. Krahn #9
Re: [Q] How to eval an EXPR once and make it stick
Sam wrote:
Yes I will. :-)>
> Thanks for all your responses; I learned a bit.
>
> 1. I wasn't clear on $_ in my email; that's being read elsewhere in program so
> it's already set by the time print_lines is called.
>
> 2. Will you bet your life on this equivalence: "not /^\s*$/ == /\S/"?
Another point that I just noticed is that you are using eof with the <>
special readline operator. You DO realize that eof (without
parenthesis) behaves differently than eof() or eof(ARGV) when using <>?
John
--
use Perl;
program
fulfillment
John W. Krahn Guest
-
Tassilo Von Parseval #10
Re: [Q] How to eval an EXPR once and make it stick
On Wed, Jan 28, 2004 at 09:11:51AM -0800 Sam wrote:
These function-refs look fishy. All they do is carrying out a pattern> 4. As for the generalized case, I learned about using refs. Anonymous subs
> also work.
>
> my $re = sub { return /^\s*$/; };
> my $nre = sub { return not &$re; };
> my $expr = $blank ? $re : $nre;
> do ... while (&$expr and not eof);
>
> But I'm not sure which is faster though.
match. By using '&$expr' you'll also have perl pass on the current
content of @_ to the function which is wasteful since you are not
interested in the arguments.
In this case you better just use pre-compiled regexes:
my $re = qr/^\s*$/;
my $nre = qr/\S/; # !qr/^\s*$/ wont work unfortunately
my $pat = $blank ? $re : $nre;
do ... while /$pat/o and not eof;
This has the disadvantage that there is no generalized way of negating a
pattern. You have to do that manually. Or you create a slightly more
complicated condition:
do ... while ($blank && /$re/) || !/$re/ and not eof;
Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus}) !JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexi ixesixeseg;y~\n~~dddd;eval
Tassilo Von Parseval Guest
-
John W. Krahn #11
Re: [Q] How to eval an EXPR once and make it stick
Sam wrote:
It depends on how you use eval. :-) Instead of using eval inside of a>
> --- Rob Dixon <rob@dixon.port995.com> wrote:>> > Sam wrote:> >> > >
> > > But I'm not sure which is faster though.
> > If you don't know, it doesn't matter.
> >
> > If your software is /too/ slow and you would die for a 10% speed increase
> > then
> > check out
> >
> > use Benchmark;
> >
> > If not, don't bother.
> No it hums along fine. But using eval was *really* slow and clearly I was on
> the wrong track using it.
loop it is a lot faster if you eval the whole loop.
# slow
my $expr = '/$regex/';
while ( <FILE> ) {
if ( eval $expr ) {
do { something() };
}
}
# a lot faster
my $loop = <<'LOOP';
while ( <FILE> ) {
if ( /$regex/ ) {
do { something() };
}
}
LOOP
eval $loop;
John
--
use Perl;
program
fulfillment
John W. Krahn Guest
-
Rob Dixon #12
Re: [Q] How to eval an EXPR once and make it stick
John W. Krahn wrote:
Nice one John. Thanks.>
> Instead of using eval inside of a loop it is a
> lot faster if you eval the whole loop.
>
> # slow
> my $expr = '/$regex/';
> while ( <FILE> ) {
> if ( eval $expr ) {
> do { something() };
> }
> }
>
> # a lot faster
> my $loop = <<'LOOP';
> while ( <FILE> ) {
> if ( /$regex/ ) {
> do { something() };
> }
> }
> LOOP
> eval $loop;
Rob
Rob Dixon Guest
-
Rob Dixon #13
Re: [Q] How to eval an EXPR once and make it stick
Sam wrote:
Yes. $_ is magical, and there's no excuse that I can think of for>
> Rob wrote:>> >
> > Sam wrote:> >> > > 1. I wasn't clear on $_ in my email; that's being read elsewhere in
> > > program so it's already set by the time print_lines is called.
> > You /mustn't/ use $_ like that. It's meant to be an 'it' in places like
> What? You want me to pass the line around in a variable! :-)
assigning to it directly. If you have a tiny block that needs to use
the same value several times then use the idiom
for ($thisvalue) {
:
}
Rob
Rob Dixon Guest



Reply With Quote

