Skip Menu |

This queue is for tickets about the Object-Pad CPAN distribution.

Report information
The Basics
Id: 132393
Status: new
Priority: 0/
Queue: Object-Pad

People
Owner: Nobody in particular
Requestors: leonerd-cpan [...] leonerd.org.uk
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 0.22
Fixed in: (no value)



Subject: Consider gut-wrenching support for e.g. unit tests
Under normal conditions it's fine that object slots are private to the class. However, it's also quite normal around Perl to gut-wrench into the insides of an object during special cases like unit tests. A t/01someclass.t is usually considered tightly coupled enough to Some/Class.pm that direct hash key access isn't considered too bad. Such techniques as { local $obj->{somekey} = "some temporary value"; is( $obj->amethod, "expected result" ); } are common. Object::Pad's :repr(native) slot representation does not allow this kind of thing. Possible ideas around it: 1) A flag to force :repr(HASH) on all otherwise-native classes, so the unit test can peer inside the object, though that still leaves the question of how it determines slot index numbers: BEGIN { $Object::Pad::FORCE_HASH_REPR = 1; } use Some::Class; my $obj = Some::Class->new; { local $obj->{'Object::Pad/slots'}[4] = "a temporary value"; ... } 2) Provide a utility function to allow runtime access to named slots. `local` doesn't work with lvalue-returning functions, but Syntax::Keyword::Dynamically would. Or users can just assign without local, and assign back afterwards: use Object::Pad qw( slotsv ); use Some::Class; my $obj = Some::Class->new; { my $old = slotsv($obj, '$somekey'); slotsv($obj, '$somekey') = "a temporary value"; ... slotsv($obj, '$somekey') = $old; } -- Paul Evans
On Tue Apr 21 09:43:30 2020, PEVANS wrote: Show quoted text
> 2) Provide a utility function to allow runtime access to named slots. > `local` doesn't work with lvalue-returning functions, but > Syntax::Keyword::Dynamically would. Or users can just assign without > local, and assign back afterwards:
At first glance this suggestion would seem break for RT132364 [1] but this isn't necessarily the case. We could borrow inspiration from how gcc stores debug information for static variables hidden inside functions, by appending some counter number to the slot names to make them visible. class Some::Class { { has $data; method m1 { return $data } } { has $data; method m2 { return $data } } } my $obj = Some::Class->new; slotsv($obj, '$data.1') = "first value"; is($obj->m1, "first value"); [1]: https://rt.cpan.org/Ticket/Display.html?id=132364 -- Paul Evans
Another idea 3) The (as yet unspecified and definitely undocumented) proposed MOP API could help here. One way might be to allow meta objects for slots to act as an accessor proxy for slot data on instances: use Some::Class; my $slotmeta = Some::Class->META->get_slot( '$somekey' ); { my $obj = Some::Class->new; my $old = $slotmeta->value( $obj ); $slotmeta->value( $obj ) = "a temporary value"; ... $slotmeta->value( $obj ) = $old; } Which again, being an lvalue method call, would also work fine via Syntax::Keyword::Dynamically: { my $obj = Some::Class->new; dynamically $slotmeta->value( $obj ) = "a temporary value"; ... } -- Paul Evans