Re: Some trouble with closures
by moritz (Cardinal) on Feb 17, 2010 at 09:18 UTC
|
I'm a bit confused by your confusion.
If you want to store data that's not shared between different instances (objects) of the same class, an attribute is what you need, and what attributes are there for.
Your description that you don't want the variable shared between various objects indicates that a static variable (emulated by a lexical variable from an outer scope, or implemented by a state variable) is specifically not what you need.
I can recommend a very good book to you: Bertrand Meyer, Object-Oriented Software Construction. If you read that from cover to cover, I can guarantee that you won't confuse attributes with anything else afterwards.
closures cause various side-effects not immediately noticeable that lead to bugs
Every construct leads to bugs when used in a context where it's not appropriate.
Perl 6 - links to (nearly) everything that is Perl 6.
| [reply] |
|
|
I second moritz. You've created a persistent state variable -- a static variable in your terms -- a variable local to the class, not to the instance. Therefore, it's not reset on object creation, which is exactly what you want if you want a persistent state.
You probably don't want that, if you want it to be reset for each object; you just want an ordinary attribute -- a variable local to the instance. The traditional choice is to declare the object in the constructor as a reference to a blessed hash and store your data within the hash. There are other ways to do it, of course.
Um, by the way, if you do decide to create a persistent state variable, you might want to enclose the entire class in braces, rather than only one method:
If you do THIS, then when you $bar = Foo::new(); and later $bar->fiddle() or $bar->fuddle() it, you will still have access within those methods to $state. If you don't, and do THAT (as you described), then you will have created a state variable peculiar to the method faddle(), invisible even to other methods of the same class. Are you sure y/N?
| [reply] [d/l] [select] |
Re: Some trouble with closures
by chromatic (Archbishop) on Feb 17, 2010 at 06:32 UTC
|
I'm not sure anyone can answer your question without seeing your code and your explanation of what you're trying to do. From what I can gather, the closure is working exactly as designed. If you find yourself trying to reset the value of a closed-over lexical from an object constructor, you're in for a world of pain. Use an object attribute for object-specific data.
| [reply] |
Re: Some trouble with closures
by WizardOfUz (Friar) on Feb 17, 2010 at 08:03 UTC
|
| [reply] |
Re: Some trouble with closures
by doug (Pilgrim) on Feb 17, 2010 at 14:27 UTC
|
Suppose you have a method of a class that you write using Moose(but a plain Perl object is also relevant), and you use inside that method a static variable (static in the C sense, by that I mean a variable that has scope local to the method but a lifetime that spans each call of said method). I was recommended that I use a closure and enclose the declaration of that variable and the method inside the closure to cause the variable to be static(again, the C sense of static).
Mixing C-think and Perl-think is not always a good idea. What you are looking for is a state variable, and that is a feature that is new with 5.10 and has to be requested. No closure is required.
Pre-5.10 you do this with a closure.
{ # open an anonymous block to form the closure
my $foo;
my $bar;
sub fubar {
# code that uses $foo and $bar
# goes in here
}
} # end of the closure
At the end of the closure the two variables go out of scope, but subsequent calls to fubar() still can use them without a problem.
- doug | [reply] [d/l] |
Re: Some trouble with closures
by JavaFan (Canon) on Feb 17, 2010 at 12:32 UTC
|
| [reply] [d/l] |
|
|
My recommendation would be to declare the variable with the static keyword inside the sub you want to static variable.
Perl 5.8.x is still the default perl for most OS's at this point. I'd recommend that someone know both ways, but unless they can be sure their project is going to be running on the latest version of perl, I'd use the slightly clunkier style. Synatic sugar is nice, but having a working program is better.
Of course, the point that they should know whether they actually want a static variable or not is right on.
| [reply] |
|
|
| [reply] |
|
|
|
|
|
|
Re: Some trouble with closures
by TGI (Parson) on Feb 19, 2010 at 00:06 UTC
|
Can you expand on what you were trying to accomplish with your variable?
Typically, you have two types of data associated with a class: class data and object data. Object data is unique for each object, and is properly stored in attributes. Class data is shared between all objects that are in the class.
Here's a very simple classical Perl OO class with both class and object data.
package MyClass;
my $instances = 0; # Class data as a lexical
sub new {
my $class = shift;
my $self = {
attribute => 'foo',
};
bless $self, $class;
$instances++;
return $self;
}
sub DESTROY {
my $self = shift;
$instances--;
return;
}
# Class data accessor
# Could also be a mutator, but it doesn't makes sense here.
sub instances {
return $instances;
}
# Class data accessor/mutator
sub attribute {
my $self = shift;
if( @_ ) {
$self->{attribute} = shift;
}
return $self->{attribute};
}
1;
| [reply] [d/l] |