Side effects of overloading quotes ""

Discussion in 'Perl Misc' started by Koszalek Opalek, Nov 28, 2007.

  1. Hello,

    I overloaded the quotes '""' in my class by using
    use overload ('""' => \&getDesc);

    I was hoping it will allow me to write
    print ("Hello from object $obj.\n");
    instead of
    print ("Hello from object " . $obj->getDesc() . ".\n");

    Well, it works that way but there are side effects that break my class
    completely.


    Problem 1)

    Before overloading
    if ($obj)
    is true, if $obj is a reference to any object of class Obj.
    If the reference is undef, $obj is false.
    After overloading "", $obj is also false if getDesc() happens to
    return an empty string! That's not what I wanted. If I did, I could
    use
    if ("$obj")


    Problem 2)

    Before overloading I could compare object references
    if ($obj1 == $obj2)
    and check if they point to the same location/object. I can no
    longer do that once the '""' operator has been overloaded.

    Operation "==": no method found,
    left argument in overloaded package Obj,
    right argument in overloaded package Obj at ./a.pl
    line 38.

    I can use eq instead of == if I also add falllback => 1 to the
    overload pragma but that string-compares $obj1->dummy()
    with $obj2->dummy() instead of object references. Again, if
    I wanted to compare the string representation I could do
    if ("$obj1" eq "$obj2")

    Am I doing sth wrong or miss the point completely? Or is this
    overload module broken beyond repair?

    I enclose a short listing that demonstrates my point.
    Uncomment one of the #use clauses to see how it breaks
    things. Any help will be appreciated.



    #!/usr/bin/perl
    use strict;
    use warnings;


    {
    package Obj;
    #use overload ('""' => \&getDesc);
    #use overload ('""' => \&getDesc, fallback => 1);


    sub new ()
    {
    my $class = shift;
    my $self = {};

    bless $self, $class;
    }

    sub getDesc ()
    {
    return "";
    };

    };

    my $obj1 = Obj->new();
    my $obj2 = Obj->new();

    ### PROBLEM 1 ###
    if ($obj1) {
    print "true\n";
    } else {
    print "false\n";
    };

    ### PROBLEM 2 ###
    if ($obj1 == $obj2) {
    print "same references\n";
    } else {
    print "different references\n";
    };

    __END__

    Koszalek
     
    Koszalek Opalek, Nov 28, 2007
    #1
    1. Advertising

  2. Koszalek Opalek <> wrote in news:914a45bc-ea5a-
    :

    > I overloaded the quotes '""' in my class by using
    > use overload ('""' => \&getDesc);
    >
    > I was hoping it will allow me to write
    > print ("Hello from object $obj.\n");
    > instead of
    > print ("Hello from object " . $obj->getDesc() . ".\n");
    >
    > Well, it works that way but there are side effects that break my class
    > completely.


    perldoc overload mentions:

    * *Boolean, string and numeric conversion*
    'bool', '""', '0+',

    If one or two of these operations are not overloaded, the remaining
    ones can be used instead. "bool" is used in the flow control
    operators (like "while") and for the ternary "?:" operation. These
    functions can return any arbitrary Perl value. If the corresponding
    operation for this value is overloaded too, that operation will be
    called again with this value.

    As a special case if the overload returns the object itself then it
    will be used directly. An overloaded conversion returning the
    object is probably a bug, because you're likely to get something
    that looks like "YourPackage=HASH(0x8172b34)".

    > Problem 1)
    >
    > Before overloading
    > if ($obj)
    > is true, if $obj is a reference to any object of class Obj.
    > If the reference is undef, $obj is false.
    > After overloading "", $obj is also false if getDesc() happens to
    > return an empty string! That's not what I wanted. If I did, I could
    > use
    > if ("$obj")


    Well, then, overload bool as well.

    > Problem 2)
    >
    > Before overloading I could compare object references
    > if ($obj1 == $obj2)
    > and check if they point to the same location/object. I can no
    > longer do that once the '""' operator has been overloaded.


    Again, overload 0+.

    > #!/usr/bin/perl
    > use strict;
    > use warnings;
    >
    >
    > {
    > package Obj;
    > #use overload ('""' => \&getDesc);
    > #use overload ('""' => \&getDesc, fallback => 1);


    Don't comment out code in your posting. That makes it hard to figure out
    exactly what code you ran.

    > sub new ()


    Don't specify prototypes for methods: They have no effect and their use
    is misleading. All this time, I have not found a good reason to use
    prototypes in my code.


    > sub getDesc ()


    Ditto for prototypes.

    > {
    > return "";
    > };
    >
    > };
    >
    > my $obj1 = Obj->new();
    > my $obj2 = Obj->new();
    >
    > ### PROBLEM 1 ###
    > if ($obj1) {
    > print "true\n";
    > } else {
    > print "false\n";
    > };
    >
    > ### PROBLEM 2 ###
    > if ($obj1 == $obj2) {
    > print "same references\n";
    > } else {
    > print "different references\n";
    > };


    The solution to Problem 1 is to implement boolean conversion. The
    solution to Problem 2 is also found in perldoc overload:

    Public functions
    Package "overload.pm" provides the following public functions:

    overload::StrVal(arg)
    Gives string value of "arg" as in absence of stringify overloading.
    If you are using this to get the address of a reference (useful for
    checking if two references point to the same thing) then you may be
    better off using "Scalar::Util::refaddr()", which is faster.


    Thus, you should also implement the equality operator.

    So, here is a reworked example. I did change method names to my liking:

    #!/usr/bin/perl
    use strict;
    use warnings;

    package Obj;

    use Scalar::Util qw( refaddr );

    use overload
    q{""} => \&to_string,
    'bool' => \&to_bool,
    q{0+} => \&to_val,
    q{==} => \&is_identical,
    ;

    sub new { bless {} => shift }

    sub to_string { q{} }

    sub to_bool { defined shift }

    sub to_val { refaddr shift }

    sub is_identical { refaddr shift == refaddr shift }

    package main;

    my $obj1 = Obj->new;
    my $obj2 = Obj->new;

    ### PROBLEM 1 ###

    print( $obj1 ? "true\n" : "false\n" );

    ### PROBLEM 2 ###

    print( $obj1 == $obj2 ? "same\n" : "different\n" );

    __END__




    --
    A. Sinan Unur <>
    (remove .invalid and reverse each component for email address)
    clpmisc guidelines: <URL:http://www.augustmail.com/~tadmc/clpmisc.shtml>
     
    A. Sinan Unur, Nov 28, 2007
    #2
    1. Advertising

  3. On Nov 28, 9:16 pm, "A. Sinan Unur" <> wrote:


    > Don't comment out code in your posting. That makes it hard to figure out
    > exactly what code you ran.


    Ok.

    > > sub new ()


    > Don't specify prototypes for methods:


    Sure.

    > So, here is a reworked example. I did change method names to my liking:
    >
    > #!/usr/bin/perl
    > use strict;
    > use warnings;
    >
    > package Obj;
    >
    > use Scalar::Util qw( refaddr );
    >
    > use overload
    > q{""} => \&to_string,
    > 'bool' => \&to_bool,
    > q{0+} => \&to_val,
    > q{==} => \&is_identical,
    > ;
    >
    > sub new { bless {} => shift }
    >
    > sub to_string { q{} }
    >
    > sub to_bool { defined shift }
    >
    > sub to_val { refaddr shift }
    >
    > sub is_identical { refaddr shift == refaddr shift }
    >
    > package main;
    >
    > my $obj1 = Obj->new;
    > my $obj2 = Obj->new;
    >
    > ### PROBLEM 1 ###
    >
    > print( $obj1 ? "true\n" : "false\n" );
    >
    > ### PROBLEM 2 ###
    >
    > print( $obj1 == $obj2 ? "same\n" : "different\n" );
    >
    > __END__



    Thank you.
    That works beautifully.

    A.


    > --
    > A. Sinan Unur <>
    > (remove .invalid and reverse each component for email address)
    > clpmisc guidelines: <URL:http://www.augustmail.com/~tadmc/clpmisc.shtml>
     
    Koszalek Opalek, Nov 29, 2007
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris White

    Quotes/Double Quotes in Image Control

    Chris White, Sep 22, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    4,855
    Hermit Dave
    Sep 22, 2004
  2. Chris
    Replies:
    1
    Views:
    13,651
    Oisin
    Mar 24, 2006
  3. Lawrence Tierney

    Multiline quotes - escaping quotes - et al

    Lawrence Tierney, Dec 24, 2003, in forum: Java
    Replies:
    3
    Views:
    4,500
    Andrew Thompson
    Dec 24, 2003
  4. rgoya
    Replies:
    7
    Views:
    609
    Edward G. Nilges
    May 20, 2004
  5. rgoya
    Replies:
    15
    Views:
    153
    Thomas 'PointedEars' Lahn
    May 21, 2004
Loading...

Share This Page