views:

129

answers:

3

PHP and .Net have closures; I have been wondering what are some examples of using closures in OOP and design patterns, and what advantages they have over pure OOP programming.

As a clarification, this is not a OOP vs. functional programming, but how to best use closures in a OOP design. How do closures fit in, say, factories or the observer pattern? What are some tricks you can pull which clarify the design and results in looser coupling, for example.

+2  A: 

Closures are useful for event-handling. This example is a bit contrived, but I think it conveys the idea:

class FileOpener
{
     public FileOpener(OpenFileTrigger trigger)
     {
         trigger.FileOpenTriggered += (sender, args) => { this.Open(args.PathToFile); };
     }

     public void Open(string pathToFile) 
     { 
         //… 
     }
}

my file opener can either open a file by directly calling instance.Open(pathToFile), or it can be triggered by some event. If I didn't have anonymous functions + closures, I'd have to write a method that had no other purpose than to respond to this event.

notJim
+2  A: 

Suppose you want to provide a class with the ability to create any number of FileOpener instances, but following IoC principles, you don't want the class creating FileOpeners to actually know how to do so (in other words, you don't want to new them). Instead, you want to use dependency injection. However, you only want this class to be able to generate FileOpener instances, and not just any instance. Here's what you can do:

class AppSetup
{
    private IContainer BuildDiContainer()
    {
         // assume this builds a dependency injection container and registers the types you want to create
    }


    public void setup()
    {
        IContainer container = BuilDiContainer();
        // create a function that uses the dependency injection container to create a `FileOpener` instance
        Func<FileOpener> getFileOpener = () => { return container.Resolve<FileOpener>(); };

        DependsOnFileOpener dofo = new DependsOnFileOpener(getFileOpener);

    }
}

Now you have your class that needs to be able to make FileOpener instances. You can use dependency injection to provide it with this capability, while retaining loose coupling

class DependsOnFileOpener()
{
    public DependesOnFileOpener(Func<FileOpener> getFileOpener)
    {
        // this class can create FileOpener instances any time it wants, without knowing where they come from
        FileOpener f = getFileOpener();
    }
}
notJim
+3  A: 

Any language that has closures can use them for trampolining, which is a technique for refactoring recursion into iteration. This can get you out of "stack overflow" problems that naive implementations of many algorithms run into.

A trampoline is a function that "bounces" a closure back up to its caller. The closure captures "the rest of the work".

For example, in Python you can define a recursive accumulator to sum the values in an array:

testdata = range(0, 1000)
def accum(items):
        if len(items) == 0:
                return 0
        elif len(items) == 1:
                return items[0]
        else:
                return items[0] + accum(items[1:])

print "will blow up:", accum(testdata)

On my machine, this craps out with a stack overflow when the length of items exceeds 998.

The same function can be done in a trampoline style using closures:

def accum2(items):
        bounced = trampoline(items, 0)
        while (callable(bounced)):
                bounced = bounced()
        return bounced

def trampoline(items, initval):
        if len(items) == 0:
                return initval
        else:
                return lambda: trampoline(items[1:], initval+items[0])

By converting recursion to iteration, you don't blow out the stack. The closure has the property of capturing the state of the computation in itself rather than on the stack as you do with recursion.

Bill Gribble
Neat trick! I don't think I've ever seen this before. Is it most common with Python (that would explain why I've never seen this)?
FrustratedWithFormsDesigner
It's quite common in the Lisp world. In most Lisp implementations, it's actually done automatically by the compiler ("tail-call optimization"). But sometimes you have to do it by hand because the compiler can only recognize the pattern in specific configurations.
Bill Gribble
I'ts not *that* common in imperative languages, but e.g. LEPL (http://www.acooke.org/lepl/) uses trampolining to prevent complex recursive descend parsers from overflowing the stack.
delnan