Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: May Thy Closures Be Blessed

by Abigail-II (Bishop)
on Apr 26, 2004 at 16:46 UTC ( [id://348245]=note: print w/replies, xml ) Need Help??


in reply to Re: May Thy Closures Be Blessed
in thread May Thy Closures Be Blessed

Both are based on lexical scoping to enforce encapsulation.
But an entire different kind of encapsulation! The closure based method as outline does data inheritance. By default, and you'll need to do work to prevent it. Inside Out objects don't do data inheritance (except if you define your subclass in the same lexical scope as your superclass - but you probably have good reasons to do so).

Furthermore, Inside Out objects don't require their superclass, or subclasses, to cooperate. With the Inside Out technique, you can subclass anything, including a closure, without interfering. Even if the superclass changes its implementation, you're safe. The closure based strategy only works if the entire inheritance tree uses the same closure.

Inside Objects are about maximizing freedom - it does not impose, and it does not require. ;-)

Abigail

Replies are listed 'Best First'.
Re: Re: May Thy Closures Be Blessed
by hardburn (Abbot) on Apr 26, 2004 at 17:58 UTC

    I wasn't at all surprised at the many comparisons to Inside-Out Objects that popped up in this thread. They both see basically the same thing wrong with Perl's object system as it is normally used and try to fix it in different ways. I must admit that the closure method didn't do some things as well as I thought it would when the idea first popped into my head a few days ago.

    With Inside-Out Objects, everything starts to look like a hash. With Closure Objects, everything starts to look like a subroutine. A subroutine call is ultimately more flexible than a hash lookup (unless you want to open the can-of-worms that is a tied interface). However, you have to put more work into it.

    IMHO, Inside-Out Objects rely on subtle behavior on Perl's part that make some people feel uneasy. Further, the technique isn't necessarily easy to grasp, even to those that have already mastered Perl's regular object system. Closures aren't necessarily easy, but I suspect they will be easier to think about than the Inside-Out technique. They may also appeal more to those with a functional programming background.

    Yes, Closure Objects do impose that the heirarchracy all use the closure technique. I think it's a net gain for freedom, even over Inside-Out Objects. It will ultimately depend on what you're trying to accomplish, though I suspect either technique will solve your problem if you put enough effort into it. Further, which technique is easier for your project may not be clear from the start.

    ----
    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      They both see basically the same thing wrong with Perl's object system as it is normally used and try to fix it in different ways
      While it may solve the problems you see with Perl's OO system, it doesn't solve any of the two biggest problems I see with the system: default data inheritance and no compile time checking of attribute names. Well, I guess one could say it solves the data inheritance problem - but in an extremely awkward way: the superclass defines the attributes of the subclasses. At least, that's how inheritance is happening in your example. Not what I call a real invitation for code reuse.
      With Inside-Out Objects, everything starts to look like a hash. With Closure Objects, everything starts to look like a subroutine. A subroutine call is ultimately more flexible than a hash lookup (unless you want to open the can-of-worms that is a tied interface). However, you have to put more work into it.
      This sound like false advertisement to me. First, your closure method eventually stores the attributes in a hash. You are just using the closure to give each object its private lexical hash. The closure doesn't provide any additional flexibility - your methods are already doing that. Methods provide the necessary flexibility, regardless of the way of storing attributes - directly in the object, in lexical class level hashes (for Inside Out objects), or in lexical object level hashes (for your closure technique).
      IMHO, Inside-Out Objects rely on subtle behavior on Perl's part that make some people feel uneasy. Further, the technique isn't necessarily easy to grasp, even to those that have already mastered Perl's regular object system.
      However, anyone having studied Damian's OO book will notice that Inside Out objects are a simple extension on "fly-weight" objects.
      They may also appeal more to those with a functional programming background.
      Frankly, I fail to see how they connect to 'functional programming'.

      Anyway, for a totally different way of doing OO using closures (no 'bless', but with inheritance, AUTOLOADING and SUPER), look at one of my earlier attempts to bypass Perl's OO problems:

        I guess one could say it solves the data inheritance problem - but in an extremely awkward way: the superclass defines the attributes of the subclasses. At least, that's how inheritance is happening in your example.

        Yes, this is something I need to think about more. I think it's possible, but the specifics haven't been worked out. (Along with a lot of other ideas).

        Much of the power of Closure Objects will depend on how much work you're willing to put into the closure.

        First, your closure method eventually stores the attributes in a hash. You are just using the closure to give each object its private lexical hash.

        That is how it is currently implemented, but there's no reason why it has to be limited to some access controls and a hash lookup. The technique enforces the "eat your own dogfood" rule (i.e., if you define accessors/mutators on class data, use them even inside the class itself). It allows for a lot of things that would otherwise have to be done by a tied interface.

        Frankly, I fail to see how they connect to 'functional programming'.

        Closures come straight out of functional programming. Plus I like ideas that combine concepts that are normally thought of as completely seperate.

        ----
        : () { :|:& };:

        Note: All code is untested, unless otherwise stated

      I predict that the closure method is worthy of the thought, but not of using. Here is my reasoning:
      1. The fact that I like closures, does not argue that I should want to always use closures. The key difference between OO and using closures heavily is in how you organize code, not how you implement things. Once I've chosen to organize things in an OO fashion, then I'm going to find my code growing in ways that OO code does, and OO design principles will be applicable.
      2. One of the big OO principles is the open-closed principle. Modules should be open for extension and closed for modification. That is, you should be able to leave a base class alone and usefully extend it by subclassing. This ideal is more often honoured in the breach than the observation, but it is worthwhile trying to think in terms of designs that can work that way.
      3. The open-closed principle says that the closure approach is worse than alternatives. You can't make unanticipated changes without either changing the base class implementation, or else working around the implementation with something like inside-out objects.
      4. Personally I value having Storable work more than I do ways of enforcing encapsulation. Therefore I don't have problems with the traditional hash approach.
Re^2: May Thy Closures Be Blessed
by adrianh (Chancellor) on Apr 26, 2004 at 17:08 UTC
    Furthermore, Inside Out objects don't require their superclass, or subclasses, to cooperate.

    They do need to co-operate over DESTROY.

      They do need to co-operate over DESTROY.
      Yes, but not more than any other form of inheritance does. If you subclass a class, and define a DESTROY method in your subclass, without calling DESTROY in the superclass, things are likely to break. Your DESTROY method should always contain something like (for single inheritance):
      $self -> SUPER::DESTROY if $ISA [0] -> can ("DESTROY");
      regardless whether you use Inside-Out objects or not.

      Abigail

        Yes, but not more than any other form of inheritance does.

        Good point.

        I guess I just worry about DESTROY with inside-out objects more because having a correct DESTROY block suddenly becomes something you need for every class with its own state, rather than something you only need for rare classes that fiddle with external resources.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (2)
As of 2024-04-25 05:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found