Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > operator in a variable?

Reply
Thread Tools

operator in a variable?

 
 
Michael Roper
Guest
Posts: n/a
 
      08-22-2003
Is it possible to store pieces of an expression in a variable that will get
expanded before the larger expression is evaluated? For example, could I
write something like: $result = $a $op $b; that would be evaluated as
$result = $a + $b;? Thanks.

Michael Roper


 
Reply With Quote
 
 
 
 
Ted Zlatanov
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> my $result = eval "$x $op $y";
> print $result;


This won't work correctly for operators that modify either variable,
because you interpolate $x and $y also; you probably want

my $result = eval "\$x $op \$y";

Ted
 
Reply With Quote
 
 
 
 
Ted Zlatanov
Guest
Posts: n/a
 
      08-22-2003
On 22 Aug 2003, (E-Mail Removed) wrote:

> my %ops = ( '+' => sub {return $_[0] + $_[1]},
> '-' => sub {return $_[0] - $_[1]},
> );
>
> my $x = 123;
> my $y = 456;
>
> for my $op ('+', '-') {
> my $result = $ops{$op}($x, $y);
> print "$x $op $y = $result\n";
> }


In case the operator needs to modify $x or $y, I would do it thus:

$ops{'+'} = sub { my $xr = shift; my $yr = shift; return $$xr + $$yr; };

my $result = $ops{$op}->(\$x, \$y);

Ted
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      08-22-2003
Ted Zlatanov <(E-Mail Removed)> writes:

> On 22 Aug 2003, (E-Mail Removed) wrote:
>
> > my %ops = ( '+' => sub {return $_[0] + $_[1]},
> > '-' => sub {return $_[0] - $_[1]},
> > );
> >
> > my $x = 123;
> > my $y = 456;
> >
> > for my $op ('+', '-') {
> > my $result = $ops{$op}($x, $y);
> > print "$x $op $y = $result\n";
> > }

>
> In case the operator needs to modify $x or $y, I would do it thus:
>
> $ops{'+'} = sub { my $xr = shift; my $yr = shift; return $$xr + $$yr; };
>
> my $result = $ops{$op}->(\$x, \$y);


That uglyness is quite unnecessary. The elements of @_ are _alaises_,
not copies, of the aguments passed to a subroutine.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
Reply With Quote
 
Sam Holden
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 06:11:48 -0400, Ted Zlatanov <(E-Mail Removed)> wrote:
> On 22 Aug 2003, (E-Mail Removed) wrote:
>
>> my %ops = ( '+' => sub {return $_[0] + $_[1]},
>> '-' => sub {return $_[0] - $_[1]},
>> );
>>
>> my $x = 123;
>> my $y = 456;
>>
>> for my $op ('+', '-') {
>> my $result = $ops{$op}($x, $y);
>> print "$x $op $y = $result\n";
>> }

>
> In case the operator needs to modify $x or $y, I would do it thus:
>
> $ops{'+'} = sub { my $xr = shift; my $yr = shift; return $$xr + $$yr; };
>
> my $result = $ops{$op}->(\$x, \$y);


$ops{'+='} = sub {$_[0] += $_[1]};
($x, $y) = (123, 456);
$ops{'+='}($x, $y);
print "$x\n";

Is the obvious example that shows you don't need to make the code
unintuitive even if you want such things.

--
Sam Holden

 
Reply With Quote
 
Francesc Guasch
Guest
Posts: n/a
 
      08-22-2003
"Janek Schleicher" <(E-Mail Removed)> wrote in message news:<(E-Mail Removed) e>...
> Michael Roper wrote at Fri, 22 Aug 2003 01:54:20 -0700:
>
> > Is it possible to store pieces of an expression in a variable that will get
> > expanded before the larger expression is evaluated? For example, could I


> perldoc -f eval
> my $result = eval "$x $op $y";
> eval STRING is one of the things that you usually won't use unless you
> really want to use it


eval is not evil, only use it with caution.

If something wrong happens running the code, the variable $@ will have
the error string.

my $result = eval "$x $op $y";
if ($@) {
# something was wrong ...
warn $@; # will show the error
# you can do something about it.
}
 
Reply With Quote
 
Michael Roper
Guest
Posts: n/a
 
      08-22-2003
Janek Schleicher writes:
> May I ask what the problem is you need to evaluate operators for.


Sure, maybe that's for the best. I have tried eval and can't get
anything to work. I need to modify a script that represents my one and only
foray into Perl, it was done a year ago, and I'm sure there's a better way.
(Also, any corrections to tortured terminology, concepts or usage on my part
is appreciated. Whatever I learned a year ago is now fuzzy at best.)

I'm starting with an ugly log generated by my server-side spam blocker. I
use one script to nicely format that log and strip out any entry that is not
a description of a blocked email. The result is a complete list of all
blocked emails, with each record formatted as (in a fixed-width font):

-----------------------------------------------------------------
Date: 04.06.2003 07:42:43

IP: 12.255.39.76
Sender: (E-Mail Removed)
Recipient: (E-Mail Removed)

Response: 550 5.2.1 Mailbox unavailable.
Reason: SPAMCOP [Spam Source, Various Others -- 127.0.0.2]
Details: Blocked - see http://spamcop.net/bl.shtml?12.255.39.76

Blacklist: www.spamcop.net
Lookup: http://www.spamcop.net/w3m?action=ch...p=12.255.39.76
-----------------------------------------------------------------

Because of the volume of blocked emails that need to be checked (for
collateral damage), I wrote a second script that further strips out log
records that are, for whatever reason, guaranteed to be spam and don't need
to be manually confirmed.

It's the second script I'm having trouble with. One of the main goals in
writing it was to make it easy to manually add, modify, or delete (within
the script itself) the "definitely spam" descriptions used to cull records
from the log. For that, I use:

my @aDelete =
({
Name => 'open relay',
Marker=> '^ Reason: (NJABL|OSIRUSOFT) \[Open Relay',
Count => "0",
},{
Name => 'china and korea',
Marker=> ' (china|korea) does not seem to care about spam$',
Count => "0",
});

When I process the log, I check each log entry ($sLogRecord) against each
Marker. If it's found, I increment the Count for the Marker. When I'm
done, I use the Name and Count for each Marker to display a summary table of
the results, as well as any log records that survived deletion (and
therefore need to be checked as possible collateral damage):

foreach $sLogRecord ( @aLogRecords )
{

#---------------------------------------------------------------------------
-----------------#
# compare against marker of each record type to be deleted

#---------------------------------------------------------------------------
-----------------#
for( $i = 0; $i <= $#aDelete; $i++ )
{
if( $sLogRecord =~ /$aDelete[$i]->{Marker}/m )
{
$aDelete[$i]->{Count}++;
$sLogRecord = undef;
}
}
}

This may be ugly, but it has worked well and I've been able to easily modify
the entries in @aDelete as needed. The problem I have now is that for the
first time I'd like to delete a record if it doesn't match a particular
Marker. So, I'd like to add an entry to @aDelete such as:

{
Name => 'invalid recipient',
Marker=> '^Recipient: michaelr@encraft\.com)$',
Count => "0",
}

and then rather than:

if( $sLogRecord =~ /$aDelete[$i]->{Marker}/m )

do this instead:

if( $sLogRecord !~ /$aDelete[$i]->{Marker}/m )

It seemed to me that the cleanest way to do this was to include the desired
operator in the @aDelete entry itself:

my @aDelete =
({
Name => 'invalid recipient',
Marker=> '^Recipient: michaelr@encraft\.com)$',
Op => "!~",
Count => "0",
},{
Name => 'open relay',
Marker=> '^ Reason: (NJABL|OSIRUSOFT) \[Open Relay',
Op => "=~",
Count => "0",
},{
Name => 'china and korea',
Marker=> ' (china|korea) does not seem to care about spam$',
Op => "=~",
Count => "0",
});

But I have been unable to find a way to then write:

if( $sLogRecord $aDelete[$i]->{Op} /$aDelete[$i]->{Marker}/m )

that will work in the intended fashion. I have tried every permutation of
eval I can think of.

I realize that I can solve this problem in other ways. It's just that the
only solutions I've come up with are pretty ugly. Any thoughts much
appreciated.

Michael Roper


 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      08-22-2003
>>>>> "FG" == Francesc Guasch <(E-Mail Removed)> writes:

>> perldoc -f eval
>> my $result = eval "$x $op $y";
>> eval STRING is one of the things that you usually won't use unless you
>> really want to use it


FG> eval is not evil, only use it with caution.

no, only use eval when is does something that is much harder (or
impossible) to do in other ways. caution is too light a word especially
when newbies are asking about eval. almost all eval uses by newbies can
be done with better and safer with hashes, code refs, dispatch tables,
etc.

the point is that eval is a last resort and not the first technique to
try. it is very rarely needed and used way too often. so the 'dogma'
here is to never support its use unless you have a clear understanding
of what it does, how it can be unsafe and a very strong reason why it is
the best solution.

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
 
Reply With Quote
 
Tad McClellan
Guest
Posts: n/a
 
      08-22-2003
Uri Guttman <(E-Mail Removed)> wrote:
>>>>>> "FG" == Francesc Guasch <(E-Mail Removed)> writes:

>


> >> my $result = eval "$x $op $y";


> FG> eval is not evil, only use it with caution.
>
> no, only use eval when is does something that is much harder (or
> impossible) to do in other ways. caution is too light a word especially
> when newbies are asking about eval. almost all eval uses by newbies can
> be done with better and safer with hashes, code refs, dispatch tables,
> etc.



For those of you following along at home, you should note that
what is being discussed here is the "eval EXPR" form.

"eval BLOCK" is not evil.


--
Tad McClellan SGML consulting
(E-Mail Removed) Perl programming
Fort Worth, Texas
 
Reply With Quote
 
Michael P. Broida
Guest
Posts: n/a
 
      08-22-2003
Michael Roper wrote:
>
> Janek Schleicher writes:
> > May I ask what the problem is you need to evaluate operators for.

>
> Sure, maybe that's for the best. I have tried eval and can't get
> anything to work. I need to modify a script that represents my one and only
> foray into Perl, it was done a year ago, and I'm sure there's a better way.
> (Also, any corrections to tortured terminology, concepts or usage on my part
> is appreciated. Whatever I learned a year ago is now fuzzy at best.)
>
> I'm starting with an ugly log generated by my server-side spam blocker. I
> use one script to nicely format that log and strip out any entry that is not
> a description of a blocked email. The result is a complete list of all
> blocked emails, with each record formatted as (in a fixed-width font):
>
> -----------------------------------------------------------------
> Date: 04.06.2003 07:42:43
>
> IP: 12.255.39.76
> Sender: (E-Mail Removed)
> Recipient: (E-Mail Removed)
>
> Response: 550 5.2.1 Mailbox unavailable.
> Reason: SPAMCOP [Spam Source, Various Others -- 127.0.0.2]
> Details: Blocked - see http://spamcop.net/bl.shtml?12.255.39.76
>
> Blacklist: www.spamcop.net
> Lookup: http://www.spamcop.net/w3m?action=ch...p=12.255.39.76
> -----------------------------------------------------------------
>
> Because of the volume of blocked emails that need to be checked (for
> collateral damage), I wrote a second script that further strips out log
> records that are, for whatever reason, guaranteed to be spam and don't need
> to be manually confirmed.
>
> It's the second script I'm having trouble with. One of the main goals in
> writing it was to make it easy to manually add, modify, or delete (within
> the script itself) the "definitely spam" descriptions used to cull records
> from the log. For that, I use:
>
> my @aDelete =
> ({
> Name => 'open relay',
> Marker=> '^ Reason: (NJABL|OSIRUSOFT) \[Open Relay',
> Count => "0",
> },{
> Name => 'china and korea',
> Marker=> ' (china|korea) does not seem to care about spam$',
> Count => "0",
> });
>
> When I process the log, I check each log entry ($sLogRecord) against each
> Marker. If it's found, I increment the Count for the Marker. When I'm
> done, I use the Name and Count for each Marker to display a summary table of
> the results, as well as any log records that survived deletion (and
> therefore need to be checked as possible collateral damage):
>
> foreach $sLogRecord ( @aLogRecords )
> {
>
> #---------------------------------------------------------------------------
> -----------------#
> # compare against marker of each record type to be deleted
>
> #---------------------------------------------------------------------------
> -----------------#
> for( $i = 0; $i <= $#aDelete; $i++ )
> {
> if( $sLogRecord =~ /$aDelete[$i]->{Marker}/m )
> {
> $aDelete[$i]->{Count}++;
> $sLogRecord = undef;
> }
> }
> }
>
> This may be ugly, but it has worked well and I've been able to easily modify
> the entries in @aDelete as needed. The problem I have now is that for the
> first time I'd like to delete a record if it doesn't match a particular
> Marker. So, I'd like to add an entry to @aDelete such as:
>
> {
> Name => 'invalid recipient',
> Marker=> '^Recipient: michaelr@encraft\.com)$',
> Count => "0",
> }
>
> and then rather than:
>
> if( $sLogRecord =~ /$aDelete[$i]->{Marker}/m )
>
> do this instead:
>
> if( $sLogRecord !~ /$aDelete[$i]->{Marker}/m )
>
> It seemed to me that the cleanest way to do this was to include the desired
> operator in the @aDelete entry itself:
>
> my @aDelete =
> ({
> Name => 'invalid recipient',
> Marker=> '^Recipient: michaelr@encraft\.com)$',
> Op => "!~",
> Count => "0",
> },{
> Name => 'open relay',
> Marker=> '^ Reason: (NJABL|OSIRUSOFT) \[Open Relay',
> Op => "=~",
> Count => "0",
> },{
> Name => 'china and korea',
> Marker=> ' (china|korea) does not seem to care about spam$',
> Op => "=~",
> Count => "0",
> });
>
> But I have been unable to find a way to then write:
>
> if( $sLogRecord $aDelete[$i]->{Op} /$aDelete[$i]->{Marker}/m )
>
> that will work in the intended fashion. I have tried every permutation of
> eval I can think of.


Combine that with someone's prior suggestion involving
using functions for the operators. Put the FUNCTION NAME
in your "Op" entry and call that function to perform the
operation needed.

Mike
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
T::operator int () const ambiguous with T::operator Handle () const? Tim Clacy C++ 15 05-30-2005 02:14 AM
Member operators operator>>() and operator<<() Alex Vinokur C++ 3 03-20-2005 03:11 PM
operator*(Foo) and operator*(int) const: ISO C++ says that these are ambiguous: Alex Vinokur C++ 4 11-26-2004 11:46 PM
Operator overloading on "default" operator John Smith C++ 2 10-06-2004 10:22 AM
Q: operator void* or operator bool? Jakob Bieling C++ 2 03-05-2004 04:27 PM



Advertisments