Andy On Closures

47 %
53 %
Information about Andy On Closures

Published on November 25, 2007

Author: melbournepatterns

Source: slideshare.net

Andy Bulka Technical Director Austhink Software www.austhink.com

Overview What are they? What languages have them? What can you do with them? Can you do the same things using regular OO?

What are they?

What languages have them?

What can you do with them?

Can you do the same things using regular OO?

Definition A closure is a block of code that can be passed around It continues to have ongoing access to variables in the scope where it was defined Ie. they are a block of code plus the bindings to the environment they came from

A closure is a block of code that can be passed around

It continues to have ongoing access to variables in the scope where it was defined

Ie. they are a block of code plus the bindings to the environment they came from

Language support Closures originated in Lisp. F unctional programming languages use them a lot e.g. Haskell Most languages have them: Smalltalk, Lisp / Scheme, Boo, Python Groovy, Ruby, C# C/C++/Java don’t

Closures originated in Lisp. F unctional programming languages use them a lot e.g. Haskell

Most languages have them:

Smalltalk,

Lisp / Scheme,

Boo, Python

Groovy,

Ruby,

C#

C/C++/Java don’t

Example – C# class Program { delegate void Action(); static Action GetAction() { int x = 0; Action a = delegate { Console.WriteLine(x); }; x = 1; return a; } static void Main(string[] args) { Action a = GetAction(); a(); } }

Example – C# class Program { delegate void SomeDelegate(); public static void InvokeMethod () { SomeDelegate del = delegate() { Console.WriteLine("Hello2"); }; del(); } } class Program { delegate void SomeDelegate(); public static void InvokeMethod () { SomeDelegate del = new SomeDelegate( SomeMethod ); del(); } static void SomeMethod() { Console.WriteLine("Hello"); } } static void Main(string[] args) { InvokeMethod (); }

Example – Python A closure is an anonymous function that ‘closes’ over its surrounding scope. Thus when the function defined by the closure is executed, it has access to all the local variables that were in scope when it was created. x = 1 def getf(y): return lambda n, m : n + m + x + y f = getf(1) print f(1,2) x += 100 print f(1,2) x = 1 def getf(y): def myf (n, m): return n + m + x + y return myf f = getf(1) print f(1,2) x += 100 print f(1,2)

A closure is an anonymous function that ‘closes’ over its surrounding scope. Thus when the function defined by the closure is executed, it has access to all the local variables that were in scope when it was created.

Uses – Summary Elegant short code fragments – no wrapping class baggage Bits of code passed to filtering/collecting methods, and for assigning methods to event handlers Single function – no wrapping class baggage inject a method as a parameter to something return a method for later use Injecting strategy Iteration - Collecting and Filtering lists Caching Setup / Cleanup Delay Evaluation Shared private state (local vars shared) Thread safety – creating multiple instances of closures New control structures Function Factories Params configure custom functions Command pattern usage

Elegant short code fragments – no wrapping class baggage

Bits of code passed to filtering/collecting methods, and for assigning methods to event handlers

Single function – no wrapping class baggage

inject a method as a parameter to something

return a method for later use

Injecting strategy

Iteration - Collecting and Filtering lists

Caching

Setup / Cleanup

Delay Evaluation

Shared private state (local vars shared)

Thread safety – creating multiple instances of closures

New control structures

Function Factories

Params configure custom functions

Command pattern usage

What’s a “block of code” Code Blocks – pass in a block vs. return a block Pass code block as a parameter to something Return the code block for someone else to use (like defining a function) Language needs to have a function passing ability C function pointers, Python functions are objects, C# delegates are type safe pointers, Java has anonymous inner classes Anonymous function vs. Named function Named functions work though anonymous more elegant Anonymity means lose the function name – but you still need to have a syntax for handling parameters

Code Blocks – pass in a block vs. return a block

Pass code block as a parameter to something

Return the code block for someone else to use (like defining a function)

Language needs to have a function passing ability

C function pointers, Python functions are objects, C# delegates are type safe pointers, Java has anonymous inner classes

Anonymous function vs. Named function

Named functions work though anonymous more elegant

Anonymity means lose the function name – but you still need to have a syntax for handling parameters

How are parameters handled? Groovy In Groovy, closure parameters are listed before the -> token, like so: def clos = { println "hello! } // without params clos() def clos = { a, b -> print a+b } // with params clos( 5, 7 )

In Groovy, closure parameters are listed before the -> token, like so:

def clos = { println "hello! } // without params

clos()

def clos = { a, b -> print a+b } // with params

clos( 5, 7 )

How are parameters handled? Python In the case of returning a code block for someone else to use, it is returned as a function e.g. def paidMore(amount): return lambda e: e.salary > amount where e is a parameter thus f = paidMore(150) // closure assigned to a variable f(sam) // closure called, with parameter

In the case of returning a code block for someone else to use, it is returned as a function e.g.

def paidMore(amount):

return lambda e: e.salary > amount

where e is a parameter thus

f = paidMore(150) // closure assigned to a variable

f(sam) // closure called, with parameter

How are parameters handled? C# DotNet has a List.FindAll() which expects a “predicate/delegate” that takes one parameter. result = gNames.FindAll( delegate(string name) { return name.StartsWith(startingText); } ); Where there delegate is declared public delegate bool Predicate<T>(T obj)

DotNet has a List.FindAll() which expects a “predicate/delegate” that takes one parameter.

Java – the final var problem e.g. Java's anonymous inner classes can access locals - but only if they are final. or if they are instance attributes, apparently public void example() { final double use=Math.random()*10000; SwingUtilities.invokeLater( new Runnable() { public void run() { System.out.println(use); } } ); }

Java's anonymous inner classes can access locals - but only if they are final. or if they are instance attributes, apparently

Java – the final var problem The second restriction to notice is that an inner class can only refer to variables from the outer lexical scope if those variables are declared to be final. This keyword tells the compiler that the binding of that variable cannot be modified at runtime. In order for an instance of an inner class to modify an outer variable, the trick is to declare the variable to be an array. Then the binding of the array is final but the element of the array is not! - Patrick Logan

The second restriction to notice is that an inner class can only refer to variables from the outer lexical scope if those variables are declared to be final. This keyword tells the compiler that the binding of that variable cannot be modified at runtime.

In order for an instance of an inner class to modify an outer variable, the trick is to declare the variable to be an array. Then the binding of the array is final but the element of the array is not! - Patrick Logan

Java – final – hack using array public interface Counter { public int current(); }  … final int [] count = new int [1]; return new Counter() { public int current() { return count[0] += 1; } }

public interface Counter {

public int current();

}

 …

final int [] count = new int [1];

return new Counter() {

public int current() {

return count[0] += 1;

}

}

Java inner classes vs closures Java inner classes are a bit verbose though (need an interface name (thus not very anonymous!) and method name wrapping the code) No local variable access either, unless variable is final Closures - which are like inner classes but have read and write access local variables C# 2.0 has true closure support in the form of anonymous delegates. This includes reading and modifying variables outside the context of the closure - unlike Java's anonymous inner classes.

Java inner classes are a bit verbose though (need an interface name (thus not very anonymous!) and method name wrapping the code)

No local variable access either, unless variable is final

Closures - which are like inner classes but have read and write access local variables

C# 2.0 has true closure support in the form of anonymous delegates. This includes reading and modifying variables outside the context of the closure - unlike Java's anonymous inner classes.

Closures add “state” The essential difference between an anonymous/inline function and a closure is that the closure continues to have ongoing access to all the variables in scope at the time it was defined. E.g. A closure has access to the local vars and even the parameters of the enclosing method if the closure was returned from a method This gives the closure not only its own internal state, but the state of its context. Thus a closure could be viewed as really an “object” since it has attributes, not just behaviour.

The essential difference between an anonymous/inline function and a closure is that the closure continues to have ongoing access to all the variables in scope at the time it was defined.

E.g. A closure has access to the local vars and even the parameters of the enclosing method if the closure was returned from a method

This gives the closure not only its own internal state, but the state of its context.

Thus a closure could be viewed as really an “object” since it has attributes, not just behaviour.

Closure “tricks” The ability of a closure to have ongoing access to state from its context allows various tricks. Pithy loops to filter and collect lists The ability of a closure to be passed around (returned from a method, passed as parameters to other methods) means the closure acts as a “prototype” and many instances can be created/cloned. Tricks (or uses) means you can create “factory methods” that return instances of closures, where each closure is configured differently due to the parameters passed into the enclosing factory method being different at the time of creation. Conversely, instances of closures can share state of local vars inside the factory method. Thus it’s a way of protected/private shared data amongst instances of closure “objects”

The ability of a closure to have ongoing access to state from its context allows various tricks.

Pithy loops to filter and collect lists

The ability of a closure to be passed around (returned from a method, passed as parameters to other methods) means the closure acts as a “prototype” and many instances can be created/cloned.

Tricks (or uses) means you can create “factory methods” that return instances of closures, where each closure is configured differently due to the parameters passed into the enclosing factory method being different at the time of creation.

Conversely, instances of closures can share state of local vars inside the factory method. Thus it’s a way of protected/private shared data amongst instances of closure “objects”

Why not just use objects? Why not pass an object or return an object. The receiver code simply calls a method on the object to do the work. Simple. Why all the fuss about passing functions as first class objects, or blocks of code “closures” as first class objects? E.g. Java’s use of anonymous inner classes are arguably a nice compromise – declaring a thin OO wrapper around a single method.

Why not pass an object or return an object. The receiver code simply calls a method on the object to do the work. Simple.

Why all the fuss about passing functions as first class objects, or blocks of code “closures” as first class objects?

E.g. Java’s use of anonymous inner classes are arguably a nice compromise – declaring a thin OO wrapper around a single method.

Why not just use anonymous inner classes? It is certainly true that for any program you can write using closures, you can write a roughly equivalent program using anonymous inner classes. That's because the Java programming language is Turing-complete. But you will probably find yourself resorting to a significant and awkward refactoring of the code that has nothing to do with the purpose of the code.

It is certainly true that for any program you can write using closures, you can write a roughly equivalent program using anonymous inner classes. That's because the Java programming language is Turing-complete. But you will probably find yourself resorting to a significant and awkward refactoring of the code that has nothing to do with the purpose of the code.

Uses – injecting strategy Write to console vs. to a file etc. – choice of strategy a = delegate { Console.WriteLine(x); }; a();

Write to console vs. to a file etc. – choice of strategy

Uses – injecting strategy – Use OO Setting up a method on an object etc. (strategy pattern). Yes more wiring…

Setting up a method on an object etc. (strategy pattern).

Yes more wiring…

Uses - iteration - filtering Iterating over lists, and filtering / collecting More elegant code e.g. pass the algorithm as a block of code e.g. Ruby: The closure technique allows you to use a one-liner. offices = [] for e in employees offices << e.office end offices = employees.collect {|e| e.office}

Iterating over lists, and filtering / collecting

More elegant code e.g. pass the algorithm as a block of code e.g. Ruby:

The closure technique allows you to use a one-liner.

Uses – iteration – filtering – Requires Library support All these Ruby closure tricks require deep library support anyway (not necessarily a bad thing…) viz. Designers of software libraries can allow users to customize behavior by passing closures as arguments to important functions. E.g. C# List.FindAll() takes a function/delegate as a parameter to use as the match function managersOffices = employees. select {|e| e.manager?}. map {|m| m.office} managers, plebs = employees. partition {|e| e.manager?} allManagers = employees. all ? {|e| e.manager?} noManagers = ! employees. any ? {|e| e.manager?} sortedEmployees = employees. sort {|a,b| a.lastname <=> b.lastname} sortedEmployees = employees. sort_by {|e| e.lastname}

All these Ruby closure tricks require deep library support anyway (not necessarily a bad thing…) viz.

Designers of software libraries can allow users to customize behavior by passing closures as arguments to important functions.

E.g. C# List.FindAll() takes a function/delegate as a parameter to use as the match function

Uses - iteration – filtering – Use List Comprehensions Python has alternative facility called “list comprehensions” Very powerful… can also have if statements in them: Sure, doesn’t handle everything that closures can do, but handles 90% of the select/collect/filter jobs well. Very popular addition to the python language. offices = [e.office for e in employees] managersOffices = [e.office for e in employees if e.isManager]

Python has alternative facility called “list comprehensions”

Very powerful… can also have if statements in them:

Sure, doesn’t handle everything that closures can do, but handles 90% of the select/collect/filter jobs well. Very popular addition to the python language.

Uses - iteration – filtering – Use Loops or OO What’s wrong with a for loop? ;-) Easy to understand, though more verbose If there is so much library support needed anyway, why not avoid closures and invent library/framework support that takes objects as parameters and calls a method on it E.g. a collection could have a method called FindAll(o) that calls Match() on the object passed in to determine if each item in the collection makes it into the result list. Injecting an object (or anon inner class method) as a strategy – simple, though possibly more verbose since you have to declare and instantiate each strategy class. Apparently this is laborious to use in practice, but doable.

What’s wrong with a for loop? ;-) Easy to understand, though more verbose

If there is so much library support needed anyway, why not avoid closures and invent library/framework support that takes objects as parameters and calls a method on it

E.g. a collection could have a method called FindAll(o) that calls Match() on the object passed in to determine if each item in the collection makes it into the result list. Injecting an object (or anon inner class method) as a strategy – simple, though possibly more verbose since you have to declare and instantiate each strategy class. Apparently this is laborious to use in practice, but doable.

Uses - Caching The solution is to build delayed objects so that the first time they are forced, they store the value that is computed. Subsequent forcings will simply return the stored value without repeating the computation. In other words, we implement delay as a special-purpose memoized procedure similar to the one described in exercise  3.27 . One way to accomplish this is to use the following procedure, which takes as argument a procedure (of no arguments) and returns a memoized version of the procedure. The first time the memoized procedure is run, it saves the computed result. On subsequent evaluations, it simply returns the result. (define (memo-proc proc)   (let ((already-run? false) (result false))     (lambda ()       (if (not already-run?)           (begin (set! result (proc))                  (set! already-run? true)                  result)           result))))

The solution is to build delayed objects so that the first time they are forced, they store the value that is computed. Subsequent forcings will simply return the stored value without repeating the computation. In other words, we implement delay as a special-purpose memoized procedure similar to the one described in exercise  3.27 . One way to accomplish this is to use the following procedure, which takes as argument a procedure (of no arguments) and returns a memoized version of the procedure. The first time the memoized procedure is run, it saves the computed result. On subsequent evaluations, it simply returns the result.

(define (memo-proc proc)   (let ((already-run? false) (result false))     (lambda ()       (if (not already-run?)           (begin (set! result (proc))                  (set! already-run? true)                  result)           result))))

Uses - Caching C# translation static SomeDelegate Cache( SomeDelegate f) {     bool alreadyrun = false ;     int result = -1;     return delegate     {         if (!alreadyrun)         {             result = f();  // run it             alreadyrun = true ;         }         return result;     }; }

C# translation

Uses - Caching C# usage of caching – proof it works     class Program     {         delegate int SomeDelegate ();         static void Main( string [] args)         {             int rez;             SomeDelegate del;                         del = Cache(Calculate);             rez = del();             Console .WriteLine(rez);             rez = del();  // this time, will return the cached value.             Console .WriteLine(rez);         }         static int Calculate()   // the function we are trying to cache         {             Console .Write( &quot;... &quot; );             return 5;         } ... 5 5 Press any key to continue . . .

C# usage of caching – proof it works

Uses – Caching – Use OO Use lazy instantiation code (manually write each time). Use proxy pattern to cache Hard to generalise the closure to work with any number/combination of parameters and return values so using the OO proxy design pattern just as easy/hard to generalise.

Use lazy instantiation code (manually write each time).

Use proxy pattern to cache

Hard to generalise the closure to work with any number/combination of parameters and return values so using the OO proxy design pattern just as easy/hard to generalise.

Uses - set up, then clean up in encapsulating operations that must be set up, and then cleaned up after. E.g. in Ruby File.open(filename) {|f| doSomethingWithFile(f)} Here the open method opens the file, executes the supplied block, and then closes it. This can be a very handy idiom for things like transactions (remember to commit or rollback) or indeed anything where you have to remember to do something at the end. I use this extensively in my xml transformation routines.

in encapsulating operations that must be set up, and then cleaned up after.

E.g. in Ruby

File.open(filename) {|f| doSomethingWithFile(f)}

Here the open method opens the file, executes the supplied block, and then closes it. This can be a very handy idiom for things like transactions (remember to commit or rollback) or indeed anything where you have to remember to do something at the end. I use this extensively in my xml transformation routines.

Uses - set up, then clean up E.g. in Ruby encapsulating operations that must be set up, and then cleaned up after. Here's an example that does both: IO.foreach(&quot;foo.txt&quot;) do |line| if (line =~ /total: (d+)/) puts $1; end end This code searches a file, and prints the matches. The IO.foreach takes care of opening the file, delivering each line to our closure, then closing the file.

E.g. in Ruby encapsulating operations that must be set up, and then cleaned up after. Here's an example that does both:

IO.foreach(&quot;foo.txt&quot;) do |line|

if (line =~ /total: (d+)/)

puts $1;

end

end

This code searches a file, and prints the matches. The IO.foreach takes care of opening the file, delivering each line to our closure, then closing the file.

Uses - set up, then clean up – Use OO Is the idea then: fp = open(“file.txt) // step 1 fp.write( CODEBLOCK ) // step 2 fp.close() // step 3 Isn’t it just a matter of organising your code? Use try/finally Use C#’s “using” construct which always cleans up Use “template method” design pattern instead and override the middle step

Is the idea then:

fp = open(“file.txt) // step 1

fp.write( CODEBLOCK ) // step 2

fp.close() // step 3

Isn’t it just a matter of organising your code?

Use try/finally

Use C#’s “using” construct which always cleans up

Use “template method” design pattern instead and override the middle step

Uses – delay evaluation Closures delay evaluation—i.e., they do not &quot;do&quot; anything until they are called

Closures delay evaluation—i.e., they do not &quot;do&quot; anything until they are called

Uses – delay evaluation My python situation builds a list of functions, then I execute them much later, when all the info available. class View(object): def __init__(self, viewname): self.cmds = [] def SetLocation(self, node , x, y): f = lambda : &quot; &quot; + &quot;view.SetLocation(%s, %d, %d)&quot; % ( node .ToNodeName(), x, y) self.cmds.append(f) def SetOffset(self, node1, node2 , x, y): f = lambda : &quot; &quot; + &quot;view.SetOffset(%s, %s, %d, %d)&quot; % ( node1 .ToNodeName(), node2 .ToNodeName(), x, y) self.cmds.append(f) # store lambdas/closures since don't want to execute each node.ToNodeName() till each rootnode.RecalcIndexes has been called for c in self.cmds: resultstr += c() + CRLF // executes the lambda

My python situation builds a list of functions, then I execute them much later, when all the info available.

Uses – delay evaluation Original solution class Node: def __init__(self, val): self.val = val def get(node): return lambda n, m : str(n) + &quot; &quot; + str(m+1) + &quot; &quot; + str(node.val) node = Node(10) f = get(node) print f(1,2) # 1, 3, 10 node.val = 100 print f(1,2) # 1, 3, 100

Original solution

Uses – delay evaluation – Use OO Another way to do it. Pure OO. def get2(node): class Late: def __init__(self, node): self.node = node def Execute(self, n, m): return str(n) + &quot; &quot; + str(m+1) + &quot; &quot; + str(self.node.val) return Late(node) node = Node(10) o = get2(node) print o.Execute(1,2) # 1, 3, 10 node.val = 100 print o.Execute(1,2) # 1, 3, 100

Another way to do it. Pure OO.

Uses – delay evaluation – Use eval Another way to do it would be to create the code as a string and then later eval(code) Only supported in dynamic languages, or languages with ability to compile at runtime.

Another way to do it would be to create the code as a string and then later eval(code)

Only supported in dynamic languages, or languages with ability to compile at runtime.

Uses – share private state Share state in a local scope place. Two or more places that use a closure can store info into the closure’s local namespace. Closure acts as a ‘object’ with behaviour and state Multiple functions can be produced which close over the same environment, enabling them to communicate privately by altering that environment (in languages that allow assignment).

Share state in a local scope place. Two or more places that use a closure can store info into the closure’s local namespace. Closure acts as a ‘object’ with behaviour and state

Multiple functions can be produced which close over the same environment, enabling them to communicate privately by altering that environment (in languages that allow assignment).

Uses – share private state Closures can be used to create additional scopes that can be used to group interrelated and dependent code in a way that minimises the risk of accidental interaction. Suppose a function is to build a string and to avoid the repeated concatenation operations (and the creation of numerous intermediate strings) the desire is to use an array to store the parts of the string in sequence and then output the results using the Array.prototype.join method (with an empty string as its argument). The array is going to act as a buffer for the output, but defining it locally to the function will result in its re-creation on each execution of the function, which may not be necessary if the only variable content of that array will be re-assigned on each function call. A Closure allows the buffer array to be associated (and neatly packaged) with the function that is dependent upon it and simultaneously keep the property name to which the buffer array as assigned out of the global namespace and free of the risk of name conflicts and accidental interactions. See http://www.jibbering.com/faq/faq_notes/closures.html and http://www.litotes.demon.co.uk/js_info/private_static.html and http://www.crockford.com/javascript/private.html for details on how javascript does this. Its all a bit much, frankly for a regular OO programmer ;-)

Closures can be used to create additional scopes that can be used to group interrelated and dependent code in a way that minimises the risk of accidental interaction. Suppose a function is to build a string and to avoid the repeated concatenation operations (and the creation of numerous intermediate strings) the desire is to use an array to store the parts of the string in sequence and then output the results using the Array.prototype.join method (with an empty string as its argument). The array is going to act as a buffer for the output, but defining it locally to the function will result in its re-creation on each execution of the function, which may not be necessary if the only variable content of that array will be re-assigned on each function call.

A Closure allows the buffer array to be associated (and neatly packaged) with the function that is dependent upon it and simultaneously keep the property name to which the buffer array as assigned out of the global namespace and free of the risk of name conflicts and accidental interactions.

See http://www.jibbering.com/faq/faq_notes/closures.html and http://www.litotes.demon.co.uk/js_info/private_static.html and http://www.crockford.com/javascript/private.html for details on how javascript does this. Its all a bit much, frankly for a regular OO programmer ;-)

Uses – share private state – Use OO Use OO instead ! Instances of objects, shared state via protected static or use aggregation – all instances point to shared object Etc.

Use OO instead !

Instances of objects, shared state via protected static

or use aggregation – all instances point to shared object

Etc.

Uses – thread safety Prototype cloning can help with thread safety cos making copies of code not sharing a central shared piece of code. (though object instances make copies too). So its about shared data really.

Prototype cloning can help with thread safety cos making copies of code not sharing a central shared piece of code. (though object instances make copies too). So its about shared data really.

Uses – thread safety One possibility might be tempting to place a lock on &quot;g_StartingText&quot;. This would certainly make the function thread-safe but it has some drawbacks. The biggest issue with this approach is that threads will not be able to access this function concurrently. If a thread acquires the lock, all other threads must wait until that thread is finished. In other words, this method becomes a potential bottleneck because only one thread can access it at a time and if there any additional processors on the machine they won't be used. The solution is to use an anonymous method to create a closure and remove the shared state:

One possibility might be tempting to place a lock on &quot;g_StartingText&quot;. This would certainly make the function thread-safe but it has some drawbacks. The biggest issue with this approach is that threads will not be able to access this function concurrently. If a thread acquires the lock, all other threads must wait until that thread is finished. In other words, this method becomes a potential bottleneck because only one thread can access it at a time and if there any additional processors on the machine they won't be used.

The solution is to use an anonymous method to create a closure and remove the shared state:

Uses – thread safety Even with the verbosity of anonymous methods, the code has been greatly reduced. And, assuming that &quot;g_Names&quot; will never be modified, this function could run concurrently on multiple threads and multiple cores without any synchronization. static List<string> GetNamesStartingWith(string startingText) { return g_Names.FindAll( delegate(string name) { return name.StartsWith(startingText); }); } static string g_StartingText; static bool NameStartsWith(string name) { return name.StartsWith(g_StartingText); } static List<string> GetNamesStartingWith(string startingText) { g_StartingText = startingText; return g_Names.FindAll(NameStartsWith); }

Even with the verbosity of anonymous methods, the code has been greatly reduced. And, assuming that &quot;g_Names&quot; will never be modified, this function could run concurrently on multiple threads and multiple cores without any synchronization.

Uses – thread safety – use OO Yeah but can use alternative OO technique: class Searcher { string g_StartingText; // local to each instance  public Searcher(string s) { g_StartingText = s; } public bool NameStartsWith(string name) { return name.StartsWith(g_StartingText); } } static List<string> GetNamesStartingWith(string startingText) { Searcher s = new Searcher(startingText); // use object to hide shared state return g_Names.FindAll(s.NameStartsWith); }

Yeah but can use alternative OO technique:

Uses - new control structures Closures allow you to add new control structures to your language. With closures, such language constructs become unnecessary (Ruby has only very primitive native looping constructs) because you can define your own. Because closures delay evaluation—i.e., they do not &quot;do&quot; anything until they are called—they can be used to define control structures. For example, all Smalltalk's standard control structures, including branches (if/then/else) and loops (while and for), are defined using objects whose methods accept closures. Users can easily define their own control structures as well.

Closures allow you to add new control structures to your language. With closures, such language constructs become unnecessary (Ruby has only very primitive native looping constructs) because you can define your own.

Because closures delay evaluation—i.e., they do not &quot;do&quot; anything until they are called—they can be used to define control structures.

For example, all Smalltalk's standard control structures, including branches (if/then/else) and loops (while and for), are defined using objects whose methods accept closures. Users can easily define their own control structures as well.

Uses - new control structures It’s the ability to return out of the closure OR out of the enclosing method (Ruby has syntax for both) which allows new control structures to be built. The latter return style (return out of the enclosing method) would lend itself to defining new control structure. Example: ?

It’s the ability to return out of the closure OR out of the enclosing method (Ruby has syntax for both) which allows new control structures to be built.

The latter return style (return out of the enclosing method) would lend itself to defining new control structure.

Example: ?

Uses - new control structures – Use OO Iterator? Define an object model which supports pluggable algorithms for iteration control, passing in your “code block” as an object with a method in it.

Iterator?

Define an object model which supports pluggable algorithms for iteration control, passing in your “code block” as an object with a method in it.

Uses - function factory Function factory – define a function with a parameter for use later e.g. javascript this technique is a prelude to command pattern use in the next section function AdderFactory(y) { return function(x){return x + y;} } var MyFunc; if (whatever) MyFunc = AdderFactory(5); else MyFunc = AdderFactory(10); print(MyFunc(123)); // Either 133 or 128. The anonymous inner function remembers what the value of y was when it was returned, even though y has gone away by the time the inner function is called! We say that the inner function is closed over the containing scope, or for short, that the inner function is a closure.

Function factory – define a function with a parameter for use later e.g. javascript this technique is a prelude to command pattern use in the next section

Uses - function factory – Use OO Function factory – define a function with a parameter for use later e.g. javascript. Result is either 133 or 128. def AdderFactory(y): return lambda x : x + y if False: MyFunc = AdderFactory(5); else: MyFunc = AdderFactory(10); print MyFunc(123) class Adder: def __init__(self, y): self.y = y def Add(self, x): return x + self.y if False: o = Adder(5) else: o = Adder(10) print o.Add(123)

Function factory – define a function with a parameter for use later e.g. javascript. Result is either 133 or 128.

Uses – command Pattern Closures are also great for implementing the Command pattern. Command implementations that use objects must explicitly have their state set up for them, closures can just close over whatever state is around when they are created. Provide parameters for functions  closure “object” = command object The closure provides parameters for the execution of a function prior to the execution of that function. For example, when a function is to be provided as the first argument to the setTimout function that is common in web browser environments. setTimeout( function(){alert(msg) }, 1000);

Closures are also great for implementing the Command pattern. Command implementations that use objects must explicitly have their state set up for them, closures can just close over whatever state is around when they are created.

Provide parameters for functions  closure “object” = command object

The closure provides parameters for the execution of a function prior to the execution of that function. For example, when a function is to be provided as the first argument to the setTimout function that is common in web browser environments.

setTimeout( function(){alert(msg) }, 1000);

Uses - command Pattern Function 1 that returns a function 2 with state Timer invokes function 2 (no params allowed – command pattern)

Function 1 that returns a function 2 with state

Timer invokes function 2 (no params allowed – command pattern)

Uses - command Pattern – Use OO Technique came from javascript where there are no classes (as usually understood) and doing things functionally – calling functions – is prevalent. Surely objects do this better/just as well? Configure an object and pass that in. The Timer calls the .Execute() method. I.e. just use the traditional Command Pattern

Technique came from javascript where there are no classes (as usually understood) and doing things functionally – calling functions – is prevalent.

Surely objects do this better/just as well?

Configure an object and pass that in.

The Timer calls the .Execute() method.

I.e. just use the traditional Command Pattern

Are Closures really that cool? The inventor of Python – Guido van Rossum – resists adding any further closure support to Python Anonymous lambdas are restricted to one statement Otherwise you can use a named function Guido believes behaviour + data = instance (not closure) Doesn’t want too much hard core “functional programming” weirdness to get into Python. Functional programming is a different paradigm! Existing List Comprehensions cover 90% of use cases.

The inventor of Python – Guido van Rossum – resists adding any further closure support to Python

Anonymous lambdas are restricted to one statement

Otherwise you can use a named function

Guido believes behaviour + data = instance (not closure)

Doesn’t want too much hard core “functional programming” weirdness to get into Python. Functional programming is a different paradigm!

Existing List Comprehensions cover 90% of use cases.

Summary – OO vs closures Arguably….  Stateful functions should be implemented as methods of classes. Behaviour + data = instance (not closure) In Javascript you e.g. create “objects” via functions birthing closure functions with various params plugged in. Apparently you get used to this alternative OO paradigm, and still do OO coding as normal - eventually. There are many paradigms for programming – lets not build too many techniques into the one language or we confuse people Objects can do anything that closures can Zen parable – study both and discover that each can do what the other can. Enlightenment.

Arguably….  Stateful functions should be implemented as methods of classes. Behaviour + data = instance (not closure)

In Javascript you e.g. create “objects” via functions birthing closure functions with various params plugged in. Apparently you get used to this alternative OO paradigm, and still do OO coding as normal - eventually.

There are many paradigms for programming – lets not build too many techniques into the one language or we confuse people

Objects can do anything that closures can

Zen parable – study both and discover that each can do what the other can. Enlightenment.

Add a comment

Related pages

Plastic & Aluminum Bottle Caps/Closures, Bottle Capping ...

Plastic and Aluminum Closures / Bottle Caps. CSI Closures feature innovative design, precision engineering and unmatched sealing integrity and tamper evidence.
Read more

School closures, student learning, and the new system of ...

Andy Smarick. April 28, ... But probably the most challenging and controversial aspect of this new approach relates to school closures, ...
Read more

Andy On Closures - Technology - documents.mx

1.Andy Bulka Technical Director Austhink Software www.austhink.com 2. Overview What are they? What languages have them? What can you do with them? Can you ...
Read more

About us » Silgan White Cap Europe/Asia - Silgan Closures

About Silgan White Cap. Silgan White Cap is specialised in the manufacture of metal, composite and plastic vacuum closures.
Read more

Back closure - Wikipedia

A back closure is a means for fastening a garment at the rear, such as with a zipper, hooks-and-eyes or buttons. Back closures were once common on Western ...
Read more

Road closures to begin along A453 between Kegworth and ...

THE Highways Agency is advising road users of the start of weekly overnight closures on the A453 as part of the ongoing widening improvement in ...
Read more

Scheme 3: Closures - YouTube

A key feature of functions in Scheme are closures. Andy Balaam explains that functions carry around the environment in which they were created ...
Read more

Silgan Closures - Home » Silgan White Cap Europe/Asia

Silgan White Cap offers much more than high quality closures..... Further information Services . Equipment. Cap Feeders, Sealing Machines & Dud Detectors.
Read more

Andy Rutledge - Gestalt Principles of Perception - 5: Closure

Archive; Gestalt Principles of Perception - 5: Closure. August 25, 2009 | By Andy Rutledge. It is no accident that the final installment in this article ...
Read more