Introduction
Martin Fowler has a good introduction to closures on his bliki.
Syntax
There are two syntaxes for closures: a block based syntax with syntactically significant whitespace and a braces based that ignores whitespace.
Block based syntax
button = Button(Text: "Click me") button.Click += def (): print("${button} was clicked!") print("and yes, this is just like any other block...")
Braces based
button1 = Button(Text: "Click me", Click: { print("clicked!") }) button2 = Button(Text: "Me too!") button2.Click = { print("${button2} was clicked!"); print("whitespace is ignored inside {}..."); print("that's why you need to use semicolons to include multiple statements..."); print("but please, dont write code like this just becase you can :)") }
Semantics
Boo closures have have full access (to read and write) to their enclosing lexical environment. For Instance:
a = 0 # declare a new variable getter = { return a } setter = { value | a = value } assert 0 == getter() setter(42) assert 42 == getter() assert 42 == a
The best source of information right now are the test cases for closures in the tests/testcases/integration directory.
Closures vs. Functions
See Functions As Objects.
Some things you can do with named functions that you cannot with closures include recursion and overloading:
This will not work because "c" is unknown from inside the closure:
c = do(x as int): print x --x c(x) if x > 0 c(5)
so you can use a regular named function or else create a 2nd callable to hold the name:
def c(x as int): print x --x c(x) if x > 0 c(5) //or: d as callable c = do(x as int): print x --x d(x) if x > 0 d = c c(5)
And you can regular named functions for overloading a method:
def doit(x as int):
print x
def doit(x as string):
print x
doit(3)
