Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: How will you use state declared variables in Perl6?

by BrowserUk (Patriarch)
on Jul 08, 2005 at 21:07 UTC ( [id://473565]=note: print w/replies, xml ) Need Help??


in reply to How will you use state declared variables in Perl6?

So how will you use state declared variables

With great caution!

Globals are trouble, no matter how you label them. Closures are much safer.

In your example, foo() is a global sub, so there can never be two instances of it, but if foo() was a method, multiple instances of whatever class foo() was a method of, would all share the same %seen. Effectively, %seen becomes a Class variable. These can be useful--eg. counting the number of instances created or in existiance--but why not use a Class variable instead?

The danger lies in that if I inherit a new class from that class, instances of both classes will access and modify the single %seen. Whilst there maybe legitimate reasons to do this, they are much rarer and harder to see, as whatever values are contained in %seen, they will represent a classic mix of apples and oranges.

This is giving the potential to create the same sort of problems we see in Perl5 with it's global vars. Eg. $| & $/ & $\ -- Having to use one function (select), to control which handle setting $| will affect is a pita.

However, not having a similar possibility to control which handle, setting applied to $/ and $\ will affect, is worse. The separation and encapsulation of state is what makes OO so useful.

I can see state vars being used to hold things like DB handles (wrapped inside singleton classes if you must :), but done that way, it stops you from writing singleton factories. I also see problems with even this use.

If P6 objects are going to be usable across threads, then using state varibles for singletons is going to produce potential problems where, for example, DB handles can only be used from one thread.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
  • Comment on Re: How will you use state declared variables in Perl6?

Replies are listed 'Best First'.
Re^2: How will you use state declared variables in Perl6?
by revdiablo (Prior) on Jul 08, 2005 at 21:40 UTC
    Closures are much safer.

    Perhaps I'm misunderstanding, but I was under the impression that the Perl6 code:

    sub foo { state $bar; $bar++; }

    Was equivalent to the Perl5 code:

    { my $bar; sub foo { $bar++; } }

    Which is a closure if I ever saw one. How is this safer? I'm not trying to blindly disagree with you, I'm honestly curious why the closure is safer.

      I believe BrowserUK's point is that if foo is just a global subroutine, there is no difference. On the other hand, suppose you had
      package Bar; sub new { ... } sub foo { state $bar; $bar++; return $bar; }
      Then later...
      $bar1 = Bar->new(); $bar2 = Bar->new(); $bar1->foo(); # returns 1, as you would expect $bar1->foo(); # returns 2, as you would expect $bar2->foo(); # returns 3, possibly unexpected
      At least this is my understanding. Is this what you meant, BrowserUK?
        jgallagher,
        BrowserUk's response boils down to "don't use state variables as a replacement for class variables when doing OO". I agree with that. The argument that it will be easy to make this mistake is false though as p6 OO looks visually a lot different from p5 (method foo() vs sub foo() for instance). I am not saying caution isn't warranted, but this is just once case that doesn't negate the usefulness elsewhere.

        Cheers - L~R

        Update: I reworded my response to be clearer but I believe the spirit of the message was left in tact.

        Yes. That is a good example of the possible surprise factor.

        Now inherit Class Qux from Class Bar, and every time you call ->foo() from any instance of either class, state $bar will be incremented. This has the potential for an even bigger surprise factor I think.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.

      I don't think that's the type of closure BrowserUk is referring to. Think more of this perl 5 code:

      sub genclosure { my $bar; return sub { $bar++; } }
      Each time you call genclosure, you get a new closure, a new state variable. You don't reuse the previously existing state variable.

      So I would have to agree with BrowserUk's "very carefully" statement. The same as I would use your perl5 (global) closure code - very carefully. That said, I have probably about a half-dozen or so places where I need or want to cache data globally in my projects at work, so this would be very nice syntactical sugar for that. However, I also generate a few closures where this new idea could easily bite a junior programmer in the arse when they wonder why their data isn't returning properly. ("How did that counter get so high already?")

      That said, I also generally avoided static in C as well, so that's not really surprising for me. After all, one generally looks at programming tasks from the basis of their experience - if it looks like a nail, that may be because all you have is a hammer.

      Update: TimToady's response has cleared things up a bit, thankfully. It was looking a bit grim for state - although there is still some care to be taken. I'll have to think if I can figure out where I'd use this feature, if anywhere.

        If that's what he meant, this would be the equivalent Perl6 code, using state:

        sub genclosure { return sub { state $bar; $bar++; } }

        I'm still not seeing a difference in safety.

Re^2: How will you use state declared variables in Perl6?
by Limbic~Region (Chancellor) on Jul 08, 2005 at 21:51 UTC
    BrowserUk,
    Globals are trouble, no matter how you label them. Closures are much safer.

    I am sure that neither you nor I have any confusion as to how state variables in Perl6 will work, but I want to respond to this as I think it may lead others astray. A variable's visibility declared with state is still restricted to the scope it was declared in. The difference from a regular lexicals is that if program execution comes back to that scope the variable is not re-initizalized and its previous value is restored. Update: TimToady has explained it much better.

    In your example, foo() is a global sub, so there can never be two instances of it, but if foo() was a method, multiple instances of whatever class foo() was a method of, would all share the same %seen. Effectively, %seen becomes a Class variable. These can be useful--eg. counting the number of instances created or in existiance--but why not use a Class variable instead?

    You are correct - variables declared with state can be used to simulate class variables just as the example I provided shows. In that case, OO didn't exist yet. Unlike p5, methods and subs will be very distinguishable in Perl6. That should make it easier to distinguish when it is more appropriate to use a class variable - but caution is warranted.

    However, not having a similar possibility to control which handle, setting applied to $/ and $\ will affect, is worse. The separation and encapsulation of state is what makes OO so useful.

    This is fixed in Perl6.

    If P6 objects are going to be usable across threads, then using state varibles for singletons is going to produce potential problems where, for example, DB handles can only be used from one thread.

    The bulk of your reply seems to be focused on how state declared variables may cause problems with OO. Nothing in my post indicated that's how I thought they should be used other than to say if you don't have OO yet - they make simulating it easier. The example I gave was that of a regular sub - not a method. I asked for examples of how others might use it. From your reply, I can assume you won't be using it for OO. Can you think of any other places you might use it for?

    Cheers - L~R

      Hmm. I would need to understand the difference between state and local, and the scope on the namespace in which state variables live.

      Ie. Does state $foo; refer to the same thing across packages, files, modules, threads?

      In single threaded apps, a truely global (process wide) variable type has uses for things like DB handles, file handles, sockets, ports, etc. anything that is a truely process global entity.

      Once you introduce threads into the equations, things get sticky. It very much depends upon the threading models supported by the OS and which of those models is used by libraries supplying services to your process as to whether things like DB handles can be safely used across threads or not.

      One assumes that the state keyword came into being in order to support a particular scenario. A good description of that scenario, and the implications of would be nice to see.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re^2: How will you use state declared variables in Perl6?
by Anonymous Monk on Jul 08, 2005 at 21:15 UTC
    Effectively, %seen becomes a Class variable

    Not so! A class variable is accessible to all instances of a class. A state variable (assuming it behaves more or less exactly like a static variable in C/C++) is visible only within the declaring function, and if that function is a method, then it is restricted to the instance as well. It's actually a tighter scope than member variables with the same persistence.

      The scope is constrainted to the method, but the potential to affect change to it is not!

      Any instance that can call the method can change it's value. Any method in the same class can call the method, therefore any instance of the class can call the method, and unless it is somehow constrained, any instance of any subclass can call a method that will call a that method and so change it's state.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://473565]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2024-04-23 21:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found