Beefy Boxes and Bandwidth Generously Provided by pair Networks RobOMonk
Perl: the Markov chain saw
 
PerlMonks  

Hints Towards Writing a Module with New Operators

by swampyankee (Parson)
on Dec 19, 2009 at 22:30 UTC ( #813561=perlquestion: print w/ replies, xml ) Need Help??
swampyankee has asked for the wisdom of the Perl Monks concerning the following question:

I'm looking for some hints on how to write a module which adds new (and largely superfluous) operators to Perl, specifically to replicate Fortran's .EQV. and .NEQV. logical operators. I won't argue that these are useful additions to Perl–I've programmed Fortran for close to forty years and never used either–but it does seem like a fun little project.


Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

Comment on Hints Towards Writing a Module with New Operators
Re: Hints Towards Writing a Module with New Operators
by moritz (Cardinal) on Dec 19, 2009 at 22:48 UTC
    Take a look at Devel::Declare, if I remember correctly it allows you to install callbacks in the parser for things that are otherwise syntax errors.

    In Perl 6 you could just declare the operators:

    use v6; multi sub infix:<.EQV.>($x, $y) { $x == $y }; say 1 .EQV. 1; say 1 .EQV. 2;

    When you run this with Rakudo, it prints

    1 0
Re: Hints Towards Writing a Module with New Operators
by JadeNB (Chaplain) on Dec 20, 2009 at 00:37 UTC

    The little Fortran documentation that I can find by Googling suggests that, as moritz (implicitly) points out, .EQV. is just == on Booleans. If this is correct, are you just looking to bring to Perl the syntactic beauty of Fortran :-)—or is it that you want something that does the Boolean conversion for you, so that you can write $a .EQV. $b ** as the equivalent of $a ? $b ? 1 : 0 : $b ? 0 : 1 *?

    Either way, as moritz says, for adding new syntax to Perl-as-it-now-is, I think that the only options are syntax filters (struck out as I write it so that you don't even think about it) or Devel::Declare (which worries adamk).

    * Or ($a && $b) || !($a || $b), I suppose. UPDATE: Ha, and maybe I'd like to write my own routines for addition while I'm at it. Thanks, JavaFan. :-)

    UPDATE: ** Note that this precise syntax conflicts with string concatenation, but we shouldn't be using barewords anyway.

        Or

        1. .NEQV. ~= $a ^ $b
        2. .EQV. ~= !($a ^ $b)

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

      You could also use

      !$a == !$b

      but that relies on the fact than the true and false values returned by Perl ops are 1) always the same, and 2) numeric*. xor is definitely the way to go.

      * — They're also strings, but that's not relevant here.

      Considering .EQV. as == for booleans is more or less correct: a .eqv. b is true if a and b are either both true or both false, and it would result in false otherwise. Most modern Fortran compilers will squawk if either a or b isn't a boolean (Fortran logical), so a fragment like

      logical boole integer int int = 42 boole = .TRUE. write(*,*) 'is int .eqv. boole true?', int .eqv. boole
      will cause a compile-time error, which is, on the whole, probably a good thing. As I said in my original post, I've been programming Fortran for quite a few years and never found a use for .eqv. or .neqv.. As an aside, Fortran is insensitive to case; I tend to use uppercase for Fortran keywords and lowercase for everything else.


      Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

Re: Hints Towards Writing a Module with New Operators
by Anonymous Monk on Dec 20, 2009 at 01:20 UTC
    I thought of overload but after having gone through writing a demonstration, I discovered what appears to be a fact that logical operators like .EQV. and .NEQV. which are non-Perl can not be overloaded and that there are restrictions on what can be overloaded within Perl itself -if I understood that well- because of the degeneracy of operators and that overloading all in all can cause certain operators to lose their magical properties (ex, x=, .=) ... seeking enlightenment on this Monks..
      I discovered what appears to be a fact that logical operators like .EQV. and .NEQV. which are non-Perl can not be overloaded and that there are restrictions on what can be overloaded within Perl itself

      This is basically correct, although the wording is strange. Overloading is something applied to objects, not operators; it changes how an object behaves when an operator is applied to it, without changing the default behaviour of that operator.

      UPDATE: Perhaps the confusion comes from the term ‘operators’? Unlike some languages, the only kind of ‘operators’ that can be defined in Perl are prefix, and their names must be alphanumeric (or else invoked by &{...}-style trickery); there is no provision in Perl (or, rather, in the parser for Perl) for a user-defined infix or postfix operator—that's the price we pay for the syntactic flexibility that's already available.

      the degeneracy of operators
      I don't know what this means.
      cause certain operators to lose their magical properties (ex, x=, .=)
      Perhaps what you mean is that one can overload, say, x and x= separately, and that the overloaded behaviours need have nothing to do with one another? This is true, but not necessary: It's perfectly possible to overload, say, just x, and let Perl figure out for you how to perform x=.
        "Overloading is something applied to objects, not operators

        " There's a concept called "Operator Overloading" that allows you to provide your own versions of operators to perform operations on class objects such as addition and subtraction of these objects lest Perl would treat these objects as strings that describe the class, a "string" here represents implementation and memory address (aka, references). If an operator is not overloaded and you called say + or - to add or subtract two objects (e.g defined data types) Perl would add/subtract on something like "Date=HASH(0x80f11fc)" ergo the need for Operator overloading which is described as:

        "When you overload one of Perl's built-in operators, you define how it behaves when it's applied to objects of a particular class", from Programming Perl.

        However, it seems that with overloading, there's a mixed statement because others describe it as:

        "The module overload.pm is a standard part of the Perl distribution. It allows your objects to define how they will react to a number of Perl's operators. " from Perl.com

        "the only kind of ‘operators’ that can be defined in Perl are prefix, and their names must be alphanumeric"

        You can define addition and subtraction operators, built-in functions, prefix and post fix operators and around 50 other functions out there...

        I think the entire concept is full of hassles that can be circumvented otherways around, but this is a SWAG for I don't have such information...and this discussion is amazing and informative... keep it going....

Re: Hints Towards Writing a Module with New Operators
by duelafn (Priest) on Dec 20, 2009 at 16:58 UTC

    Sounds like fun!:

    # IHeartFortran.pm package IHeartFortran; use strict; use warnings; require Exporter; our @ISA = qw( Exporter ); our @EXPORT = qw/ EQV NEQV /; use overload '.' => \&_do_op; sub _do_op { my ($self, $y, $reverse) = @_; $$self{ $reverse ? 'left' : 'right' } = $y; if (exists($$self{left}) and exists($$self{right})) { return $$self{op}->(@$self{qw/ left right /}); } return $self; } sub new { my ($class, $op) = @_; bless { op => $op }, $class; } sub EQV() { __PACKAGE__->new( sub { $_[0] == $_[1] ? 1 : 0 } ) } sub NEQV() { __PACKAGE__->new( sub { $_[0] != $_[1] ? 1 : 0 } ) }

    Then to use it:

    #!/usr/bin/perl use strict; use warnings; use 5.010; use IHeartFortran; say 1 .EQV. 1; say 1 .EQV. 2; say 1 .NEQV. 1; say 1 .NEQV. 2;

    This doesn't exactly create a .EQV. operator (for instance, spaces would be allowed:  1 . EQV . 2), but it looks good enough.

    update: Actually, I think FORTRAN's whitespace rules would allow extra spaces anyway, so perhaps this is a somewhat faithful recreation anyway. Case flexibility on the other hand...

    Good Day,
        Dean

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://813561]
Approved by Perlbotics
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (13)
As of 2014-04-18 19:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (471 votes), past polls