On Tue, Mar 08, 2005 at 10:31:48PM +0000, Fergal Daly wrote:
No, other way around. When a TB instance needs a TB::Counter it just says $tb->counter which, normally, returns a singleton but you can alter counter()
so it returns something else.
A singleton is a class that only ever has 1 instance in existence. If there can be multiple instances of TB::Counter or TB::Run then by definition neither of them are singletons. Conversely if there is only ever 1 instance of the Test::Builder class, as chromatic said in his reply, then it is a singleton.
I never worried too much about definitions.
Point is, normally there's one and only one TB::Counter object floating around but if you really need to you can make another.
If so, what can I do if some are from depth 3 or 1?
You temporarily change the level inside the scope of that function.
So I'll have to call local on the default_level field of the TB object?
Right now that's the best I can think of.
This is why the idiom is currently:
local $Level = $Level + 2;
or whatever. You add to the existing level rather than just setting it anew.
But without a global variable there is no existing level.
Yes. This sucks.
How can I do that without a global variable?
An excellent question. It may have to be:
local $tb->{Level} = $tb->{Level} + 1;
because local doesn't work on accessors. However localizing hash keys is its own special layer of hell.
What about the "resource aquisition is initialization" approach?
package TB; sub new { bless { level => \my $level }, shift } sub obtain { TB::_level->new( shift->{level} ) } 1;
package TB::_level; sub new { ${$_[1]}++; bless { level => $_[1] }, $_[0] } sub DESTROY { ${shift()->{level}}-- } 1;
package main; use Data::Dumper;
my $tb = TB->new; print Dumper $tb; { my $l = $tb->obtain; print Dumper $tb; { my $inner_l = $tb->obtain; print Dumper $tb; } } print Dumper $tb;
__END__
There may be issues with earlier perls with the behaviour of DESTROY; I can't recall off-hand.