Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$tied_hash{overloaded_object} += 3; fails #11153

Closed
p5pRT opened this issue Feb 23, 2011 · 4 comments
Closed

$tied_hash{overloaded_object} += 3; fails #11153

p5pRT opened this issue Feb 23, 2011 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 23, 2011

Migrated from rt.perl.org#84786 (status was 'resolved')

Searchable as RT84786$

@p5pRT
Copy link
Author

p5pRT commented Feb 23, 2011

From @ikegami

Hi,

Given a tied hash that contains a value which is an object with overloads,
the following code attempts to numify the overloaded object​:

  $tied_hash{overloaded_object} += 3;

The overloaded '+=' isn't getting called. The following works fine​:

  $tied_hash{overloaded_object} = $tied_hash{overloaded_object} + 3;
  $plain_hash{overloaded_object} = $plain_hash{overloaded_object} + 3;
  $plain_hash{overloaded_object} += 3;

Tested with v5.12.2 and a recent blead (v5.13.9-284-g76cc22e).

Test case and output below.

- Eric Brine

----- BEGIN CODE -----
#!/usr/bin/env perl

use strict;
use warnings;

{
  package Test;

  use overload
  '+' => \&append,
  '+=' => \&append;

  sub append {
  my ( $self, $value ) = @​_;
  push @​$self, $value;
  return $self;
  }
}

use Test​::More tests => 3;

use Tie​::Hash qw( );

{ # Works for "+" instead of "+=".
  my %hash;
  tie %hash, 'Tie​::StdHash';
  $hash{'test'} = bless [], 'Test';

  eval { $hash{'test'} = $hash{'test'} + 3; 1 }
  or diag("$@​");

  is(3, $hash{'test'}[0], '+, tied hash');
}

{ # Works for untied hash, so it's not a problem with the overloaded object.
  my %hash;
  $hash{'test'} = bless [], 'Test';

  eval { $hash{'test'} += 3; 1 }
  or diag("$@​");

  is(3, $hash{'test'}[0], '+=, normal hash');
}

{
  my %hash;
  tie %hash, 'Tie​::StdHash';
  $hash{'test'} = bless [], 'Test';

  eval { $hash{'test'} += 3; 1 }
  or diag("$@​");

  is(3, $hash{'test'}[0], '+=, tied hash');
}
----- END CODE -----

----- BEGIN OUTPUT -----
1..3
ok 1 - +, tied hash
ok 2 - +=, normal hash
# Operation "0+"​: no method found, argument in overloaded package Test at
a.pl line 50.
not ok 3 - +=, tied hash
# Failed test '+=, tied hash'
# at a.pl line 53.
# got​: '3'
# expected​: undef
# Looks like you failed 1 test of 3.
----- END OUTPUT -----

@p5pRT
Copy link
Author

p5pRT commented Feb 24, 2011

From @iabyn

On Wed, Feb 23, 2011 at 01​:09​:06PM -0800, Eric Brine wrote​:

Given a tied hash that contains a value which is an object with overloads,
the following code attempts to numify the overloaded object​:

$tied\_hash\{overloaded\_object\} \+= 3;

The overloaded '+=' isn't getting called. The following works fine​:

$tied\_hash\{overloaded\_object\} = $tied\_hash\{overloaded\_object\} \+ 3;
$plain\_hash\{overloaded\_object\} = $plain\_hash\{overloaded\_object\} \+ 3;
$plain\_hash\{overloaded\_object\} \+= 3;

Tested with v5.12.2 and a recent blead (v5.13.9-284-g76cc22e).

Test case and output below.

- Eric Brine

----- BEGIN CODE -----
#!/usr/bin/env perl

use strict;
use warnings;

{
package Test;

use overload
   '\+'  => \\&append\,
   '\+=' => \\&append;

sub append \{
    my \( $self\, $value \) = @​\_;
    push @​$self\, $value;
    return $self;
\}

}

use Test​::More tests => 3;

use Tie​::Hash qw( );

{ # Works for "+" instead of "+=".
my %hash;
tie %hash, 'Tie​::StdHash';
$hash{'test'} = bless [], 'Test';

eval \{ $hash\{'test'\} = $hash\{'test'\} \+ 3; 1 \}
    or diag\("$@​"\);

is\(3\, $hash\{'test'\}\[0\]\, '\+\, tied hash'\);

}

{ # Works for untied hash, so it's not a problem with the overloaded object.
my %hash;
$hash{'test'} = bless [], 'Test';

eval \{ $hash\{'test'\} \+= 3; 1 \}
    or diag\("$@​"\);

is\(3\, $hash\{'test'\}\[0\]\, '\+=\, normal hash'\);

}

{
my %hash;
tie %hash, 'Tie​::StdHash';
$hash{'test'} = bless [], 'Test';

eval \{ $hash\{'test'\} \+= 3; 1 \}
    or diag\("$@​"\);

is\(3\, $hash\{'test'\}\[0\]\, '\+=\, tied hash'\);

}
----- END CODE -----

----- BEGIN OUTPUT -----
1..3
ok 1 - +, tied hash
ok 2 - +=, normal hash
# Operation "0+"​: no method found, argument in overloaded package Test at
a.pl line 50.
not ok 3 - +=, tied hash
# Failed test '+=, tied hash'
# at a.pl line 53.
# got​: '3'
# expected​: undef
# Looks like you failed 1 test of 3.
----- END OUTPUT -----

This was fixed in a recent blead. Under blead, you get instead​:

ok 1 - +, tied hash
ok 2 - +=, normal hash
# Operation "="​: no method found, argument in overloaded package Test at /tmp/p line 52.
...

because with a tie, it can't determine whether its safe to skip using the
copy constructor, so it always calls it. Adding one, e.g.

  '=' => sub { bless [ @​{$_[0]} ], 'Test' },

makes all three tests pass.

--
Any [programming] language that doesn't occasionally surprise the
novice will pay for it by continually surprising the expert.
  -- Larry Wall

@p5pRT
Copy link
Author

p5pRT commented Feb 24, 2011

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Feb 24, 2011

@iabyn - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant