maXbox Starter 31

Start with Closures
1.1 A Function Block in a Box
Today we step through a topic of closures.
One of the questions that comes up when learning closures is how they
can be useful when they're no less verbose as traditional methods of
callbacks, IoC and delegation. The answer is that closures or methods
don't have to be so verbose they are reusable. !hat are closures"
 They are a block of code plus the bindings to the environment they
came from #$agusa Idiom % function ob&ect'.
(irst we will start with an anonymous method"
procedure
begin
writeln('Anonymous method has executed');
end
This isn't very different from a normal procedure. )ou'll notice that the
procedure has no name. )ou'll also notice the missing semicolon after the
final end like others in ma*bo+ #whitespacing'.
!ithout a name, we have to call them by a reference. ,aybe you know a
procedure type as long ago used in many languages before ob&ect
oriented coding was up"
Type
TMath_Func = PROCEDURE(var x: single);
-uch a procedure type can be called or passed by reference.
.rocedure type ob&ects have the addresses of procedures as values. )ou
can specify procedure types like above" Tmath_func = rocedure.
./types are often used as parameters to other procedures like also a
closure does. This is useful when the procedure specifies an algorithm that
involves calling another procedure or function, and the called procedure or
function varies from one call to the ne+t.
var
fct!x" fct#x" fct$x: TMath_Func;
0 good e+ample of the use of a ./type is a numeric integration procedure
or a simple function plot. The procedure implements the algorithm of a
numeric math function but the function being plotted or integrated is
passed in as a parameter"
PROCEDURE nth_%ower(var x: single);
BEGIN
x:= ower(x"&);
END;
1ust like a reference to a procedure or procedure of ob&ect, a method
reference must have a type. The type must be a matching procedure or
function declaration, means of the same signature"
type
TMath_Func = PROCEDURE(var x: single);
PROCEDURE nth_%ower(var x: single); ''same match
-o how do we call that function type2
3ariables of procedure types can be assigned the value of a procedure
that has the same types of parameters and return value, and the same
attributes. !e call it"
fct$x:= (nth_%ower;
or pass it to another function"

fct_ta)le(#"!**"*+!" (nth_%ower"'ower of(x) ,losure scheme');

)ou can now make further assignments by assigning the p/type to
another reference. This reference can be another variable, a method
parameter, a class field and so on. 0s long as they are all of the same
type, assignments can be made as needed.
4ow we go back to our anonymous method on first page. 5ow do call that
method if it has no name2 $ight it must be used with a reference.
2
That reference can be a variable to which the method is assigned.
var
fct$x: TMath_Func;
var
myAnonymousMethod: Troc;
 Only procedures that are not contained in other procedures can be
assigned as the values of procedure variables. -tandard procedures
cannot be assigned as values of procedure variables.
4ow we step from anonymous methods and p/types to a closure.
)ou remember the definition"
A block of code plus the bindings to the environment they came from.
This is the formal thing that sets closures apart from function pointers,
procedure types and similar techniques.
0s more 6things6 on planet 7arth are converted to the inventory set of
digitally connected Internet devices, the roles and responsibilities of web
developers and technology managers will need to evolve with closures.
5ope you did already work with the -tarter 8 till 9:"
http://sourceforge.net/apps/mediawiki/maxbox/
!e start a closure with simplification, the image below is my sight of a
closure" the cards are functions with red variables of game state which are
enclosed by a black bo+ and can be called by ref name behind.
 -implification" )our classes are small and your methods too you;ve said
everything and you;ve removed the last piece of unnecessary code.
1.1.1 et the Closure Code
Closures are reusable blocks of code that capture the environment and
can be passed around as method arguments for immediate or deferred
e+ecution.
3
The term closure is very often treated as a synonym for the term anony/
mous methods. Though closures are specific to anonymous methods, they
are not the same concept. !hy2
The scope is missing as I want to show you now.
)ou see that our p/type has a parameter + through which I pass the
current base value to the const with e+ponent <.
PROCEDURE nth_%ower(var x: single);
BEGIN
x:= ower(x"&);
END;
-o the value 4 isn't a passed parameter to that procedure, lets define now
the closure in .ython #.ascal available in m*<'"
def generate_%ower_func(n):
print -id(n): ./- . id(n)
def nth_%ower(x):
return x00n
print -id(nth_%ower): ./- . id(nth_%ower)
return nth_%ower
5ere the inner function nth_%ower(x) is the code/block of the closure.
The trick that you want to notice in what's going on is what happens to the
value of + like x^n. The argument + is now a local variable in outer#' and
the behavior of local variables isn't normally very e+citing. =ut in this case,
+ is global to the function inner#' schema.
111 def outer(n):
+++ def inner(x):
+++ return x2n
+++ return inner
+++
111 custom3nner=outer(&)
111 custom3nner(#)
!4
0nd since inner#' uses the name, it doesn't go away when outer#' e+its.
Instead inner#' captures it or >closes over? it. )ou can now call outer#' as
many times as you like and each value of + will be captured separately@
111 ref%ow_to_& = generate_%ower_func(&) ''ref instance
111 ref%ow_to_&(#) ''call
!4
111 ref%ow_to_$ = generate_%ower_func($)
111 ref%ow_to_$(!*)
!***
!
The function that's returned is called a closure.
!hen a function is written enclosed in another function, it has full access
to local variables from the enclosing function this feature is also called
le+ical scoping.
Closures create another scope which includes any symbols used by the
anonymous method but which are not declared inside the method itself,
like the above parameter n. This scope is then bound to the anonymous
method and follows it everywhere it goes.
The image below declares this conte+t with arguments which a caller can
follow in another conte+t.
-o now you're wondering why I &ust spent this time e+plaining closures
when it works &ust like a nested method anyway and you don't have to
take any steps to make it work. !ithout closures you can think of"
A In C or .ascal you think as a function pointer or procedure type
A In 1ava as an anonymous inner class
A In Belphi or CC you would consider a delegate.
The reason is because a closure is not really a direct access to the symbols
in the outer scope #its sort of compiler magic D see appendi+' so you need
the old basics on the other hand a closure is more fle+ible and reusable
than all the others.
If you have ever written a function that returned another function, you
probably may have used the closure concept even without knowing about
them.
!e should keep 9 things in mind"
"
8. The ability to bind to local variables is part of that, but I think the big
reason is that the notation to use them is simple and clear.
E. 1ava's anonymous inner classes can access locals / but only if they
are declared final.
9. !ith closures we can avoid"
• =ad 4aming #no naming convention'
• Buplicated Code #side effects'
• Fong ,ethods #to much code' and temporary (ields #confusion'
• Fong .arameter Fist #Ob&ect is missing'
• Bata Classes #no methods'
A Farge Class and Class with too many delegating methods
A Coupled classes
!ithout closures, you would use more upper variables using parameters
and you would repeat yourself because you cant pass your function to
another function like the following counter e+. stresses"
function new,ounter ()
local i:= *
return function () ''55 anonymous function
i:= i 6 !
return i
end
end

c!:= new,ounter()
%rint(c!()) 551 !
%rint(c!()) 551 #
)ou can pass the counter function to print as many times you like and the
scope as the local var goes with the result of the call
1
, otherwise it would
be initialise by : over and over again@
1
#ote that this means that result cannot li$e onl% in C&'S()*S
+
-imply put, a closure is a function plus all it needs to access its upvalues
correctly #local vars in most of the time'. If we call new,ounter again, it
will create a new local variable i, so we will get a new closure, acting over
that new variable #and you avoid globals too@'"
c# = new,ounter()
%rint(c#()) 551 !
%rint(c!()) 551 $
%rint(c#()) 551 #
 !hy is that so interesting and important2 =ecause functions are in a
closure sense first/class values with memory of scope.

1.1.2 Some ,ractise
0s you already know the tool is split up into the toolbar across the top, the
editor or code part in the centre and the output window at the bottom.
Change that in the menu %view at our own style.
 In ma*bo+ you will not call closures only callbacks%p/types in a script,
so the part above is also an introduction to other languages but closures
are in the pipe of m*<.
 =efore this starter code will work you will need to download ma*bo+
from the website. It can be from
http"%%www.softwareschule.ch%ma+bo+.htm #you;ll find the download
ma+bo+9.Gip on the top left of the page'. Once the download has finished,
unGip the file, making sure that you preserve the folder structure as it is. If
you double/click ma*bo+9.e+e the bo+ opens a default demo program.
Test it with (H % (E or press Compile and you should hear a sound. -o far
so good now we;ll open the e+amples"
EI8JclosuresJstudyJworkingsetE.t+t
EI8JclosuresJstudyE.t+t
http"%%www.softwareschule.ch%e+amples% EI8JclosuresJstudyE.t+t
 One way in which anonymous methods are useful is by simplifying
code for common coding patterns.
(or instance, the following code pattern is probably familiar or common"
procedure Test,losureTas7;
var 8ld,ursor: T,ursor;
begin
8ld,ursor:= 9creen+,ursor;
try
9creen+,ursor:= cr:ourglass;
-
'' ;o some lengthy %rocess to show hourglass cursor
finally
9creen+,ursor:= 8ld,ursor;
end;
end;
-o, this kind of boilerplate construct calls for an anonymous method or
callback method"
type Troc = procedure;
procedure re%eatroc;
var i: integer;
begin
for i:= ! to <<<<<<< do
end;

procedure 9how:our=lass(roc: Troc);
var
8ld,ursor: T,ursor;
begin
8ld,ursor:= 9creen+,ursor;
9creen+,ursor:= cr:our=lass;
try
roc(); ''calls )ac7>
finally
9creen+,ursor:= 8ld,ursor
end;
end;

//lambda expression!
//def adder = {x,y -> return x+y}
begin
9how:our=lass((re%eatroc); ''call
The result is fewer lines of code and a general or common way to display
the hour glass cursor in all instances #dry D don't repeat yourself'.
This e+ample requires two types of units" T,ursor and 9creen the second
one is a global package value of the 3CF.
Fets take a ?closeK look at a closure as a callback"
function AlertThis?ater(message" timeout)
@
function fn() @ alert(message); A
window+setTimeout(fn" timeout);
A
AlertThis?ater(-:i" ascalB9cri%t-" $***);
.
0 closure is created containing the message parameter, fn#' is e+ecuted
quite some time after the call to AlertThis?ater has returned, yet fn#'
still has access to the original content of message@
!: /he (0 of the Closure 1pp
": 1 browser set of a closure
The increase in importance of web services, however, has made it possible
to use dynamic languages #where types are not strictly enforced at
compile time' for large scale development. Fanguages such as .ython,
$uby and .5. support closures.
 -cheme was the first language to introduce closures, allowing full
le+ical scoping, simplifying many types of programming style.
1.1.3 Closure 'b2ects
Close to the end of the last part some knowledge about ob&ect functions.
Closure ob&ects can be divided into three basic types, which reflect how a
closure was initiated and what a local ob&ect is referenced to.
3
These 9 are
A !hen a function is written enclosed in another function, it has full
access to local variables from the enclosing function this
feature is called le+ical scoping.
A 7valuating a closure e+pression produces a closure ob&ect as a
reference.
A The closure ob&ect can later be invoked, which results in e+ecution
of the body, yielding the value of the e+pression #if one was
present' to the invoker.
 Therefore the inner function can access variables in the calling function,
i.e. its closure.
The compiler has to make decisions about where the data comes from and
what it can do with that data. -ometimes it will determine that a closure is
not possible and will give you simply an error.
+: the 4'X5 1rduino and the (0 is #'/ a closure 678
19
1.2 Conclusion
Closures improve automation and integration of new methods, better
testability, efficiency and readability #simplification' and above all reuse.
• 5ow many times have you written a piece of code and thought ?I
wish I could reuse this block of codeK2
• 5ow many times have you re/factored e+isting code to remove
redundancies2
• 5ow many times have you written the same block of code more than
once before realising that an abstraction e+ists2
Code that support closures allows functions with very little synta+ and less
redundancy. !hile this might not seem an important point, I believe it's
crucial / it's the key to make it natural to use them frequently. Fook at Fisp
or or $uby and you'll see closures all over the place.
:eedback ;
max;kleiner.com
&iterature:
<leiner et al.5 ,atterns konkret5 29935 Software = Support
&inks of maXbox5 Closures and >eb of /hings:
http://www.softwareschule.ch/download/Closures?@urich2912?2.pdf
http://www.softwareschule.ch/download/closures?report.pdf
http://www.shutupandship.com/2912/91/p%thon7closures7explained.html
http://gafter.blogspot.com/299-/91/definition7ofclosures.html
http://www.softwareschule.ch/download/1rduino?C?291!?+?basta?box.pdf
http://www.softwareschule.ch/maxbox.htm
A Bichael 4olin5 CClosure: /he Definiti$e uideE5 'F)eill% Bedia6 1uflage: 1 G29. 'ktober 29198.
http://sourceforge.net/pro2ects/maxbox
http://sourceforge.net/apps/mediawiki/maxbox/
http://sourceforge.net/pro2ects/delphiwebstart
11
http://www.blaisepascal.eu/subscribers/$ogelaar?elctronics?info?english.php
maXbox 1rduino :ramework
1.3 Appendix Studies
Histor%
A &isp started in 13"3
A Scheme as a dialect of &isp
A 'ne feature of the language was function7$alued
expressions5 signified b% lambda.
A Smalltalk with 4locks.
A &isp used something called dynamic scoping.
Closures tudies and 9ources:
htt%:''tronice7+)logs%ot+com'#**C'!#'closures5closure5is5form5of5
anonymous_#D+html
htt%:''www+EaFac+info'
def generate_%ower_func(n):
print -id(n): ./- . id(n)
def nth_%ower(x):
return x00n
print -id(nth_%ower): ./- . id(nth_%ower)
return nth_%ower
111 raised_to_& = generate_%ower_func(&)
id(n): ,,FC;,
id(nth_%ower): ,&44$*
111 repr(raised_to_&)
'Gfunction nth_%ower at *x**,&44$*1'
12
111 del generate_%ower_func
111 raised_to_&(#)
!4
::
H'%h%I H%h%I # define a function within a function and return it to the
callin scope - # a inner function can access !ariables in a callin
function, its closure
def times(n):
def _f(x):
return x 0 n
return _f
t$ = times($)
print t$ #
print t$(C) # "#
H'%h%I
:ere the inner function _f() is the )loc7 of code of the closure" similar
to the la!bda code in the first exam%le+
:ere an em)edded microcontroller system seems li7e a closure as a
functional %rogramming with )loc7s of code:
RTClock: Arduino by Silvia Rothen
http://www.ecotronics.ch/ecotron/arduinocheatsheet.htm
13

Sign up to vote on this title
UsefulNot useful