[22985] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 5205 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Wed Jul 9 21:48:21 2003

Date: Wed, 9 Jul 2003 18:46:01 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Wed, 9 Jul 2003     Volume: 10 Number: 5205

Today's topics:
        Remove line <juha.jantunen@pp2.inet.fi>
    Re: Remove line <bdonlan@bd-home-comp.no-ip.org>
    Re: Remove line <noreply@gunnar.cc>
    Re: Remove line (Glenn Jackman)
    Re: Remove line <krahnj@acm.org>
    Re: Remove line <usenet@expires082003.tinita.de>
    Re: Remove line <noreply@gunnar.cc>
    Re: Remove line <usenet@expires082003.tinita.de>
    Re: Remove line <noreply@gunnar.cc>
    Re: Remove line <mgjv@tradingpost.com.au>
    Re: Remove line <noreply@gunnar.cc>
    Re: Remove line <mgjv@tradingpost.com.au>
    Re: Remove line <noreply@gunnar.cc>
    Re: Remove line (Steve Rathkopf)
    Re: Remove line <ben.goldberg@hotpop.com>
        Script Request - form mailer with ID Number <gregatwork@NOSPAMPLEASEhotmail.com>
        Seeking advice on selecting a sub (possibly/slightly re <bik.mido@tiscalinet.it>
    Re: Seeking advice on selecting a sub (possibly/slightl <nanae@perusion.com>
    Re: Seeking advice on selecting a sub (possibly/slightl nobull@mail.com
    Re: Seeking advice on selecting a sub (possibly/slightl <REMOVEsdnCAPS@comcast.net>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Tue, 08 Jul 2003 21:00:54 GMT
From: "Juha Jantunen" <juha.jantunen@pp2.inet.fi>
Subject: Remove line
Message-Id: <aiGOa.358$ir5.357@read3.inet.fi>

What is the most efective way to remove empty lines from array.

e.g I have an array  @testing = {"aa","bb","","cc","","dd","ee",""}

and I would like it have values {"aa","bb","cc","dd","ee",}

It seems that most used way is just handle the array only if(! $_ ~ /^$/)
but I would like to avoid that if.

Thanks: - jj -




------------------------------

Date: Tue, 08 Jul 2003 17:18:23 -0400
From: "bd" <bdonlan@bd-home-comp.no-ip.org>
Subject: Re: Remove line
Message-Id: <pan.2003.07.08.21.18.23.474821@bd-home-comp.no-ip.org>

On Tue, 08 Jul 2003 21:00:54 +0000, Juha Jantunen wrote:

> What is the most efective way to remove empty lines from array.
> 
> e.g I have an array  @testing = {"aa","bb","","cc","","dd","ee",""}
> 
> and I would like it have values {"aa","bb","cc","dd","ee",}
> 
> It seems that most used way is just handle the array only if(! $_ ~ /^$/)
> but I would like to avoid that if.

@testing = grep { $_ ne '' } @testing;

-- 
Freenet distribution not available
The day advanced as if to light some work of mine; it was morning, 
and lo! now it is evening, and nothing memorable is accomplished.  
		-- H.D. Thoreau



------------------------------

Date: Tue, 08 Jul 2003 23:22:09 +0200
From: Gunnar Hjalmarsson <noreply@gunnar.cc>
Subject: Re: Remove line
Message-Id: <befcu0$4e1ud$1@ID-184292.news.dfncis.de>

Juha Jantunen wrote:
> What is the most efective way to remove empty lines from array.

An array consists of elements, not lines. Probably you have a text
file that you have slurped into an array...

> e.g I have an array  @testing =
> {"aa","bb","","cc","","dd","ee",""}
--^---------------------------------^

I suppose you didn't intend that to be Perl code, since it would have
resulted in $testing[0] being assigned a hash reference...

> and I would like it have values {"aa","bb","cc","dd","ee",}

Not sure about most effective, but this is one way:

     for (0..$#testing) {
         splice @testing, $_, 1 unless $testing[$_];
     }

-- 
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl



------------------------------

Date: 8 Jul 2003 21:33:18 GMT
From: xx087@freenet.carleton.ca (Glenn Jackman)
Subject: Re: Remove line
Message-Id: <slrnbgme4v.sfp.xx087@freenet10.carleton.ca>

Juha Jantunen <juha.jantunen@pp2.inet.fi> wrote:
> e.g I have an array  @testing = {"aa","bb","","cc","","dd","ee",""}
> and I would like it have values {"aa","bb","cc","dd","ee",}

    @testing = grep {length > 0} @testing;

-- 
Glenn Jackman


------------------------------

Date: Tue, 08 Jul 2003 22:59:11 GMT
From: "John W. Krahn" <krahnj@acm.org>
Subject: Re: Remove line
Message-Id: <3F0B4CFC.BA619E20@acm.org>

Juha Jantunen wrote:
> 
> What is the most efective way to remove empty lines from array.
> 
> e.g I have an array  @testing = {"aa","bb","","cc","","dd","ee",""}
> 
> and I would like it have values {"aa","bb","cc","dd","ee",}
> 
> It seems that most used way is just handle the array only if(! $_ ~ /^$/)
> but I would like to avoid that if.

@testing = grep length, @testing;


John
-- 
use Perl;
program
fulfillment


------------------------------

Date: 8 Jul 2003 23:25:19 GMT
From: Tina Mueller <usenet@expires082003.tinita.de>
Subject: Re: Remove line
Message-Id: <befjsu$4sg40$1@ID-24002.news.dfncis.de>

Gunnar Hjalmarsson wrote:

> Not sure about most effective, but this is one way:

>      for (0..$#testing) {
>          splice @testing, $_, 1 unless $testing[$_];
>      }

uhm, not really:
$ perl -wle'
@a=("aa","bb","","","cc","");
for (0..$#a) {
 splice @a, $_, 1 unless $a[$_];
}
print "[$_]" for @a'
splice() offset past end of array at -e line 4.
[aa]
[bb]
[]
[cc]

not a good idea to change an array while iterating over it.
but you could use:
  for (reverse 0..$#a) {

and instead of "unless $a[$_]" (which will delete "0") write:
  unless length $a[$_]

regards, tina
-- 
http://www.tinita.de/     \  enter__| |__the___ _ _ ___
http://Movies.tinita.de/   \     / _` / _ \/ _ \ '_(_-< of
http://www.perlquotes.de/   \    \ _,_\ __/\ __/_| /__/ perception
- my mail address expires end of august 2003 -


------------------------------

Date: Wed, 09 Jul 2003 02:53:34 +0200
From: Gunnar Hjalmarsson <noreply@gunnar.cc>
Subject: Re: Remove line
Message-Id: <befpb3$4liuv$1@ID-184292.news.dfncis.de>

Tina Mueller wrote:
> Gunnar Hjalmarsson wrote:
>>Not sure about most effective, but this is one way:
>> 
>>     for (0..$#testing) {
>>         splice @testing, $_, 1 unless $testing[$_];
>>     }

<snip>

> not a good idea to change an array while iterating over it.

You are right of course, thanks for correcting me. I modified the 
code, and made a benchmark:

     #!/usr/bin/perl
     use strict;
     use warnings;
     use Benchmark qw(timethese cmpthese);
     my @testing = ("aa","bb","","cc","","dd","ee","");
     my @testing2 = @testing;
     my $r = timethese( -5, {
         splice => sub {
             for (my $i = $#testing - 1; $i >= 0; $i--) {
                 splice @testing, $i--, 1 unless $testing[$i];
             }
         },
         grep   => sub { @testing2 = grep length, @testing2 },
     } );
     cmpthese $r;

and it outputted:

     Benchmark: running grep, splice for at least 5 CPU seconds...
           grep:  6 wallclock secs ( 5.11 usr +  0.00 sys =
                     5.11 CPU) @ 27895.11/s (n=142544)
         splice:  5 wallclock secs ( 5.05 usr +  0.00 sys =
                     5.05 CPU) @ 78955.45/s (n=398725)
               Rate   grep splice
     grep   27895/s     --   -65%
     splice 78955/s   183%     --

I often forget about grep(), but this time it may have been good to do 
so. After all, OP asked about "the most effective way", and even if 
the "splice" method embraces more than twice as many characters to 
type, it's almost three times faster. ;-)

-- 
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl



------------------------------

Date: 9 Jul 2003 01:17:48 GMT
From: Tina Mueller <usenet@expires082003.tinita.de>
Subject: Re: Remove line
Message-Id: <befqfs$4jelr$1@ID-24002.news.dfncis.de>

Gunnar Hjalmarsson wrote:

> I often forget about grep(), but this time it may have been good to do 
> so. After all, OP asked about "the most effective way", and even if 
> the "splice" method embraces more than twice as many characters to 
> type, it's almost three times faster. ;-)

yep, splice() might be faster, but this also depends on the
number of empty elements in the array. i could imagine that
grep is faster if there are a lot of empty elements, but
i'm too tired now to try it out =)

regards, tina
-- 
http://www.tinita.de/     \  enter__| |__the___ _ _ ___
http://Movies.tinita.de/   \     / _` / _ \/ _ \ '_(_-< of
http://www.perlquotes.de/   \    \ _,_\ __/\ __/_| /__/ perception
- my mail address expires end of august 2003 -


------------------------------

Date: Wed, 09 Jul 2003 03:18:48 +0200
From: Gunnar Hjalmarsson <noreply@gunnar.cc>
Subject: Re: Remove line
Message-Id: <befqqg$4ot69$1@ID-184292.news.dfncis.de>

I'm afraid I have to correct myself...

Gunnar Hjalmarsson wrote:
> 
>             for (my $i = $#testing - 1; $i >= 0; $i--) {
------------------------------------^^^^
That reduction by 1 shall not be there.

>                 splice @testing, $i--, 1 unless $testing[$i];
>             }

-- 
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl



------------------------------

Date: Wed, 9 Jul 2003 12:48:07 +1000
From: Martien Verbruggen <mgjv@tradingpost.com.au>
Subject: Re: Remove line
Message-Id: <slrnbgn0j7.rlm.mgjv@martien.heliotrope.home>

On Wed, 09 Jul 2003 02:53:34 +0200,
	Gunnar Hjalmarsson <noreply@gunnar.cc> wrote:
> Tina Mueller wrote:
>> Gunnar Hjalmarsson wrote:
>>>Not sure about most effective, but this is one way:
>>> 
>>>     for (0..$#testing) {
>>>         splice @testing, $_, 1 unless $testing[$_];
>>>     }
> 
><snip>
> 
>> not a good idea to change an array while iterating over it.
> 
> You are right of course, thanks for correcting me. I modified the 
> code, and made a benchmark:

[snip]

>              for (my $i = $#testing - 1; $i >= 0; $i--) {
                            ^^^^^^^^^^^^^
			    that's not right.

> I often forget about grep(), but this time it may have been good to do 
> so. After all, OP asked about "the most effective way", and even if 
> the "splice" method embraces more than twice as many characters to 
> type, it's almost three times faster. ;-)

Effective does not necessarily mean that it needs to be fast. In this
case, the method with slice took two tries, and it still isn't correct.
The grep method is hard to get wrong. Apart from that, the grep method
is going to be much easier to maintain when changes need to be made.

It is never a good idea to write more complicated code in the
expectation that it will be faster, unless you _need_ it to be faster.
Always choose the simplest and easiest to follow code, unless the more
complex code has advantages that you need.

Effectiveness in programmer time is also important. Correctness is even
more important. A program that is wrong, but really fast, is still
wrong.

Martien
-- 
                        | 
Martien Verbruggen      | Blessed are the Fundamentalists, for they
                        | shall inhibit the earth.
                        | 


------------------------------

Date: Wed, 09 Jul 2003 07:34:26 +0200
From: Gunnar Hjalmarsson <noreply@gunnar.cc>
Subject: Re: Remove line
Message-Id: <beg9qc$4n4gs$1@ID-184292.news.dfncis.de>

Martien Verbruggen wrote:
> On Wed, 09 Jul 2003 02:53:34 +0200, Gunnar Hjalmarsson
> <noreply@gunnar.cc> wrote:
> 
>> I often forget about grep(), but this time it may have been good
>> to do so. After all, OP asked about "the most effective way", and
>> even if the "splice" method embraces more than twice as many
>> characters to type, it's almost three times faster. ;-)
> 
> Effective does not necessarily mean that it needs to be fast. In
> this case, the method with slice took two tries, and it still isn't
> correct.

Actually, it took three tries, and yet isn't correct...  This is the
foùrth, and hopefully last, try:

     for (my $i = $#testing; $i >= 0; $i--) {
         splice @testing, $i, 1 unless $testing[$i];
     }

> The grep method is hard to get wrong.

Okay.

> Apart from that, the grep method is going to be much easier to
> maintain when changes need to be made.

What do you mean by that?

> It is never a good idea to write more complicated code in the 
> expectation that it will be faster, unless you _need_ it to be
> faster. Always choose the simplest and easiest to follow code,
> unless the more complex code has advantages that you need.

To leave my mistakes at that, what makes code "easy to follow"
respective "complex"? Personally I find the splice method less
abstract and more intuitive. Let's say I wouldn't do any programming
the next year, and come back in a year and see these two methods for
removing elements from an array. I think I would then understand the
splice method, while I would likely need to look up 'grep'.

So, in the end, isn't it just up to personal preferences?

-- 
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl



------------------------------

Date: Wed, 9 Jul 2003 17:18:01 +1000
From: Martien Verbruggen <mgjv@tradingpost.com.au>
Subject: Re: Remove line
Message-Id: <slrnbgngd8.rlm.mgjv@martien.heliotrope.home>

On Wed, 09 Jul 2003 07:34:26 +0200,
	Gunnar Hjalmarsson <noreply@gunnar.cc> wrote:
> Martien Verbruggen wrote:

>> Apart from that, the grep method is going to be much easier to
>> maintain when changes need to be made.
> 
> What do you mean by that?

A maintenance programmer (or yourself) comes back to the code three
years later. The grep method is easy to read, and it'll take you almost
no time to change the test and be certain that it works as it should.
The code with a splice is hard to read, so after parsing it for a while,
you change the test, and then you have to reread the splice bit to make
sure it really only removes the single element and doesn't do anything
else, like move elememts around so that the loop is certainly no longer
valid.

Some 90% (yes, I made that number up) of maintenance programming is
reading code to understand it. 

> 
>> It is never a good idea to write more complicated code in the 
>> expectation that it will be faster, unless you _need_ it to be
>> faster. Always choose the simplest and easiest to follow code,
>> unless the more complex code has advantages that you need.
> 
> To leave my mistakes at that, what makes code "easy to follow"
> respective "complex"? Personally I find the splice method less
> abstract and more intuitive. Let's say I wouldn't do any programming
> the next year, and come back in a year and see these two methods for
> removing elements from an array. I think I would then understand the
> splice method, while I would likely need to look up 'grep'.

Well, I have the feeling that for most Perl programmers it is the other
way around. Most people would know how grep works without having to look
it up, but for me, splice is always one of those functions that I look
up, just to make sure I've got the arguments right. I hardly ever use
splice. I use grep all the time. This is the sort of thing that grep is
there for.

> So, in the end, isn't it just up to personal preferences?

That depends. If you only write code for yourself, then yes. However, if
you write code for other people, and the likelihood that other people
need to read it, then no, it isn't a case of personal preferences, but
it is a case of making things as legible as possible.

If I had to review code that used splice in that way, I'd probably
insist on a decent comment to explain what is going on. Maybe it's a
difference in background between us: I have worked in teams a lot, and
have maintained large amounts of code (not just Perl) written by other
people. I've come to really dislike code that chooses a "faster" routine
above a clearly and idiomatically written one, especially if there is no
documentation explaining why that choice was made. It means I have to
read the code to understand it, then I have to wonder why the original
programmer didn't choose the more obvious/idiomatic path, and then I
have to change it. Often I just replace the whole thing.

Martien
-- 
                        | 
Martien Verbruggen      | Think of the average person. Half of the
                        | people out there are dumber.
                        | 


------------------------------

Date: Wed, 09 Jul 2003 15:31:23 +0200
From: Gunnar Hjalmarsson <noreply@gunnar.cc>
Subject: Re: Remove line
Message-Id: <beh5pj$55tcg$1@ID-184292.news.dfncis.de>

Martien Verbruggen wrote:
> The code with a splice is hard to read,

Well, I don't agree on that. IMO it is a straight-forward code that 
explicitly shows you what it does, and I find it very hard to 
understand why you seem to claim that grep is 'good' and splice is 
'bad' code. On the other hand, it's not the first time I react when 
somebody in this group paints the world in black and white as regards 
Perl style matters. In my world there are much more colours, at least 
256^3 of them...

To avoid possible misunderstandings, let me add that I think that most 
of your reasoning makes much sense. Not convinced, though, that the 
choice between grep and splice is a good area to apply it. :)

-- 
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl



------------------------------

Date: 9 Jul 2003 08:23:48 -0700
From: srathkopf@juno.com (Steve Rathkopf)
Subject: Re: Remove line
Message-Id: <ae8d5bef.0307090723.3c5b077b@posting.google.com>

Martin,

I am only now learning Perl, but I have been maintaining [other
language] code for about 15 years as a contractor and as an employee.

All I can say to your comments is "RIGHT ON!"

Steve
************************************************************
Martien Verbruggen <mgjv@tradingpost.com.au> wrote in message news:<slrnbgngd8.rlm.mgjv@martien.heliotrope.home>...
> On Wed, 09 Jul 2003 07:34:26 +0200,
> 	Gunnar Hjalmarsson <noreply@gunnar.cc> wrote:
> > Martien Verbruggen wrote:
>  
> >> Apart from that, the grep method is going to be much easier to
> >> maintain when changes need to be made.
> > 
> > What do you mean by that?
> 
> A maintenance programmer (or yourself) comes back to the code three
> years later. The grep method is easy to read, and it'll take you almost
> no time to change the test and be certain that it works as it should.
> The code with a splice is hard to read, 

<<<<<< large snip>>>>>>> 

> That depends. If you only write code for yourself, then yes. However, if
> you write code for other people, and the likelihood that other people
> need to read it, then no, it isn't a case of personal preferences, but
> it is a case of making things as legible as possible.
> 
> If I had to review code that used splice in that way, I'd probably
> insist on a decent comment to explain what is going on. Maybe it's a
> difference in background between us: I have worked in teams a lot, and
> have maintained large amounts of code (not just Perl) written by other
> people. I've come to really dislike code that chooses a "faster" routine
> above a clearly and idiomatically written one, especially if there is no
> documentation explaining why that choice was made. It means I have to
> read the code to understand it, then I have to wonder why the original
> programmer didn't choose the more obvious/idiomatic path, and then I
> have to change it. Often I just replace the whole thing.
> 
> Martien


------------------------------

Date: Wed, 09 Jul 2003 19:40:36 -0400
From: Benjamin Goldberg <ben.goldberg@hotpop.com>
Subject: Re: Remove line
Message-Id: <3F0CA7F4.6CEC2EBB@hotpop.com>



Gunnar Hjalmarsson wrote:
> 
> Tina Mueller wrote:
> > Gunnar Hjalmarsson wrote:
> >>Not sure about most effective, but this is one way:
> >>
> >>     for (0..$#testing) {
> >>         splice @testing, $_, 1 unless $testing[$_];
> >>     }
> 
> <snip>
> 
> > not a good idea to change an array while iterating over it.
> 
> You are right of course, thanks for correcting me. I modified the
> code, and made a benchmark:
> 
>      #!/usr/bin/perl
>      use strict;
>      use warnings;
>      use Benchmark qw(timethese cmpthese);
>      my @testing = ("aa","bb","","cc","","dd","ee","");
>      my @testing2 = @testing;
>      my $r = timethese( -5, {
>          splice => sub {
>              for (my $i = $#testing - 1; $i >= 0; $i--) {
>                  splice @testing, $i--, 1 unless $testing[$i];
>              }
>          },

You aren't restoring @testing after each test, so it will be faster than
it would be RL.


>          grep   => sub { @testing2 = grep length, @testing2 },

Hmm, you aren't restoring @testing2 after each test, either.

>      } );
>      cmpthese $r;
> 
> and it outputted:
> 
>      Benchmark: running grep, splice for at least 5 CPU seconds...
>            grep:  6 wallclock secs ( 5.11 usr +  0.00 sys =
>                      5.11 CPU) @ 27895.11/s (n=142544)
>          splice:  5 wallclock secs ( 5.05 usr +  0.00 sys =
>                      5.05 CPU) @ 78955.45/s (n=398725)
>                Rate   grep splice
>      grep   27895/s     --   -65%
>      splice 78955/s   183%     --
> 
> I often forget about grep(), but this time it may have been good to do
> so. After all, OP asked about "the most effective way", and even if
> the "splice" method embraces more than twice as many characters to
> type, it's almost three times faster. ;-)

The following code gives different results:

   use strict;
   use warnings;
   use Benchmark qw(timethese cmpthese);

   my @testing = ("aa","bb","","cc","","dd","ee","");
   my @testing2 = @testing;
   my $r = timethese( -5, {
      Splice_1 => sub {
         @testing = @testing2;
         for(my $i = $#testing - 1; $i >= 0; $i--) {
            splice @testing, $i--, 1 unless $testing[$i];
         }
         ();
      }, Splice_2 => sub {
         @testing = @testing2;
         for my $i (reverse 0 .. $#testing - 1) {
            splice @testing, $i--, 1 unless $testing[$i];
         }
         ();
      }, Grep => sub {
         @testing = @testing2;
         @testing = grep length, @testing;
         ();
      },
   } );
   cmpthese( $r );
   __END__

[Windows 95] C:\WINDOWS\TEMP>perl test.pl
Benchmark: running Grep, Splice_1, Splice_2, each for at least 5 CPU
seconds...
    Grep:  6 wallclock secs (5.44 CPU) @ 8575.00/s (n=46648)
Splice_1:  4 wallclock secs (5.11 CPU) @ 6118.40/s (n=31265)
Splice_2:  5 wallclock secs (5.17 CPU) @ 5684.91/s (n=29391)
           Rate Splice_2 Splice_1     Grep
Splice_2 5685/s       --      -7%     -34%
Splice_1 6118/s       8%       --     -29%
Grep     8575/s      51%      40%       --

PS: I just copied the "$#testing - 1" ... why do you have *that*,
instead of $#testing directly?

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


------------------------------

Date: Wed, 9 Jul 2003 08:19:14 +0800
From: "gwmbox" <gregatwork@NOSPAMPLEASEhotmail.com>
Subject: Script Request - form mailer with ID Number
Message-Id: <befn22$js9$1@ftp.curtin.edu.au>

Hi all

I am looking for a basic form mailer script that can assign a unique
sequential number to each request, if anyone knows of one please let me
know.

Thanks

Greg




------------------------------

Date: Wed, 09 Jul 2003 14:36:35 +0200
From: Michele Dondi <bik.mido@tiscalinet.it>
Subject: Seeking advice on selecting a sub (possibly/slightly related to cmd line switches)
Message-Id: <8vvngvkocsj3nsrgeo2jum53o3aipe6j69@4ax.com>

I'm not sure the subject line is appropriate. Couldn't come up with
anything better...

Well, just to be definite (but not limited to the following example),
suppose I have to accomplish different tasks according to some cmd
line switches for a script. Say all of them involve 'while (<>)
{...}', so I do *not* want to test the switch for every iteration and
I do *not* want to repeat big portions of code either.

It seems to me that the "best" solution that doesn't clobber the main
logic of the program is something along the lines of the following
example. But I'm not sure if it is the "right(TM) thing" to do: can
you comment please?

  #!/usr/bin/perl
  # Oversimplified example
  use strict;
  use warnings;
  use Term::ANSIColor qw/:constants/;
  use Getopt::Std;
  
  sub doit;
  
  my %opt;
  getopts 'c', \%opt;
  if ($opt{'c'}) {
      *doit = sub {
  	local $_=shift;
  	print if s/\b(foo)\b/RED.$1.RESET/ge
      }
  }
  else {
      *doit = sub {
  	local $_=shift;
  	print if /\bfoo\b/;
      }
  }
  
  doit $_ while <>;
  __END__

Also, as an aside, and since I'm very curious, having heard that
basically in Perl6 "everything will be an object", I wonder if it will
provide hooks for the beginning and the end of a sub, or possibly for
a label inside it, as in the following pseudo-code:

sub doit {
    ...
}

doit.END = {
    print STDERR "$.: foo" if $foo;
} if $verbose;


Michele
-- 
$\=q.,.,$_=q.print'  ,\g,,( w,a'c'e'h,,map{$_-=qif/g/;chr
}107..q[..117,q)[map+hex,split//,join' ,2B,, w$ECDF078D3'
F9'5F3014$,$,];];$\.=$/,s,q,32,g,s,g,112,g,y,' , q,,eval;


------------------------------

Date: Wed, 9 Jul 2003 15:59:10 +0000 (UTC)
From: Perusion hostmaster <nanae@perusion.com>
Subject: Re: Seeking advice on selecting a sub (possibly/slightly related to cmd line switches)
Message-Id: <slrnbgoeut.dti.nanae@ns.valuemedia.com>

On Wed, 09 Jul 2003 14:36:35 +0200, Michele Dondi <bik.mido@tiscalinet.it> wrote:
> I'm not sure the subject line is appropriate. Couldn't come up with
> anything better...
> 
> Well, just to be definite (but not limited to the following example),
> suppose I have to accomplish different tasks according to some cmd
> line switches for a script. Say all of them involve 'while (<>)
> {...}', so I do *not* want to test the switch for every iteration and
> I do *not* want to repeat big portions of code either.
> 
> It seems to me that the "best" solution that doesn't clobber the main
> logic of the program is something along the lines of the following
> example. But I'm not sure if it is the "right(TM) thing" to do: can
> you comment please?

I believe it is right if it works...but you might find it more
flexible to map your subs to a hash or something. The code below
allows you to add an alternative processing routine by adding
one hash member...of course if you used Getopt::Long and some
appropriate logic you could name them as well.

#!/usr/bin/perl

# Oversimplified example
use strict; 
use warnings;
use Term::ANSIColor qw/:constants/;
use Getopt::Std;

my $sub;
my %opt;

my %dispatch = (
    g       =>  sub {
                    my $arg = shift;
                    print $arg if $arg =~ s/\b(bar)\b/GREEN . $1 . RESET/ge;
                },
    c       =>  sub {
                    my $arg = shift;
                    print $arg if $arg =~ s/\b(foo)\b/RED . $1 . RESET/ge;
                },
    default =>  sub {
                    local $_=shift;
                    print if /\bfoo\b/;
                },
); 

my $optstring = join '', grep length($_) == 1, keys %dispatch;

getopts $optstring, \%opt; 

my @subs = sort keys %opt;

push @subs, 'default' unless @subs;

while(defined (my $line = <>) ) {
	$dispatch{$_}->($line) for @subs;
}

__END__

-- 
Perusion Hostmaster

"Being against torture ought to be sort of a bipartisan thing."
-- Karl Lehenbauer


------------------------------

Date: 9 Jul 2003 10:23:35 -0700
From: nobull@mail.com
Subject: Re: Seeking advice on selecting a sub (possibly/slightly related to cmd line switches)
Message-Id: <4dafc536.0307090923.7790cd46@posting.google.com>

Michele Dondi <bik.mido@tiscalinet.it> wrote in message news:<8vvngvkocsj3nsrgeo2jum53o3aipe6j69@4ax.com>...
> I'm not sure the subject line is appropriate. Couldn't come up with
> anything better...

It looks quite good to me.

> Well, just to be definite (but not limited to the following example),
> suppose I have to accomplish different tasks according to some cmd
> line switches for a script. Say all of them involve 'while (<>)
> {...}', so I do *not* want to test the switch for every iteration and
> I do *not* want to repeat big portions of code either.
> 
> It seems to me that the "best" solution that doesn't clobber the main
> logic of the program is something along the lines of the following
> example. But I'm not sure if it is the "right(TM) thing" to do: can
> you comment please?

>   if ($opt{'c'}) {
>       *doit = sub {
>   	local $_=shift;
>   	print if s/\b(foo)\b/RED.$1.RESET/ge
>       }
>   }
>   else {
>       *doit = sub {
>   	local $_=shift;
>   	print if /\bfoo\b/;
>       }
>   }
>   
>   doit $_ while <>;

Looks OK to me, iff not being able to alter the code that calls doit()
was one of your criteria.

If not then I'd use the anon subs directly rather than munging the
sumbol table.

Also it is not necessary to use the formal paramter passing mechanism
all the time (although some people perfer to).  The other way of
calling subroutines does have it's place, and this, IMHO is it.

my $doit = do {
  if ($opt{c}) {
      sub {
   	print if s/\b(foo)\b/RED.$1.RESET/ge
       }
   }
   else {
     sub {
   	print if /\bfoo\b/;
   }
 }
};
   
&$doit while <>;


------------------------------

Date: Wed, 09 Jul 2003 18:26:30 -0500
From: "Eric J. Roode" <REMOVEsdnCAPS@comcast.net>
Subject: Re: Seeking advice on selecting a sub (possibly/slightly related to cmd line switches)
Message-Id: <Xns93B3C5C19F6C6sdn.comcast@206.127.4.25>

-----BEGIN xxx SIGNED MESSAGE-----
Hash: SHA1

Michele Dondi <bik.mido@tiscalinet.it> wrote in 
news:8vvngvkocsj3nsrgeo2jum53o3aipe6j69@4ax.com:

> I'm not sure the subject line is appropriate. Couldn't come up with
> anything better...
> 
> Well, just to be definite (but not limited to the following example),
> suppose I have to accomplish different tasks according to some cmd
> line switches for a script. Say all of them involve 'while (<>)
> {...}', so I do *not* want to test the switch for every iteration and
> I do *not* want to repeat big portions of code either.
> 
> It seems to me that the "best" solution that doesn't clobber the main
> logic of the program is something along the lines of the following
> example. But I'm not sure if it is the "right(TM) thing" to do: can
> you comment please?
> 
>   #!/usr/bin/perl
>   # Oversimplified example
>   use strict;
>   use warnings;
>   use Term::ANSIColor qw/:constants/;
>   use Getopt::Std;
>   
>   sub doit;
>   
>   my %opt;
>   getopts 'c', \%opt;
>   if ($opt{'c'}) {
>       *doit = sub {
>        local $_=shift;
>        print if s/\b(foo)\b/RED.$1.RESET/ge
>       }
>   }
>   else {
>       *doit = sub {
>        local $_=shift;
>        print if /\bfoo\b/;
>       }
>   }
>   
>   doit $_ while <>;
>   __END__

That looks like it'd work.  I think I personally would have done it 
differently; I'd put a code reference into a scalar variable, $doit, and 
then run the main loop as

    $doit->($_) while <>;

You could do this via dispatch table:

    sub something {...la la la ...}
    sub anotherthing {... la la la ...}
    sub morethings { ...la la la ...}

    my %dispatch = (
        one   => \&something,
        two   => \&anotherthing,
        three => \&morethings,
    );

    my $doit = $dispatch{$option};
    $doit->($_) while <>;
    # or even:
    $dispatch{$option}($_) while <>;


> Also, as an aside, and since I'm very curious, having heard that
> basically in Perl6 "everything will be an object", I wonder if it will
> provide hooks for the beginning and the end of a sub, or possibly for
> a label inside it, as in the following pseudo-code:
> 
> sub doit {
>     ...
> }
> 
> doit.END = {
>     print STDERR "$.: foo" if $foo;
> } if $verbose;

You can do this in Perl 5.  No need to wait for hell to freeze over, 
which is approximately when Perl 6 will be ready for prime time. See the 
Hook::LexWrap module (although the wrappers are not "lexical" as the name 
implies, but rather dynamic).

- -- 
Eric
$_ =  reverse sort qw p ekca lre Js reh ts
p, $/.r, map $_.$", qw e p h tona e; print

-----BEGIN xxx SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPwyknmPeouIeTNHoEQIkWgCeK7k6eY9ydDezjP8Bk27xOxLa3yAAoJNx
BNf6YlcL9eGs7j8nnAOiTRF1
=+nTa
-----END PGP SIGNATURE-----


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc.  For subscription or unsubscription requests, send
the single line:

	subscribe perl-users
or:
	unsubscribe perl-users

to almanac@ruby.oce.orst.edu.  

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.

For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V10 Issue 5205
***************************************


home help back first fref pref prev next nref lref last post