# Advanced topics __See also:__ [parallelism]. ## Closures/scopes isolation Each block has own scope, in which it can safely use closures and override outer vars. Lets use some lambdas to create isolated scopes: var param = "global" val prefix = "param in " val scope1 = { var param = prefix + "scope1" param } val scope2 = { var param = prefix + "scope2" param } println(scope1()) println(scope2()) println(param) >>> param in scope1 >>> param in scope2 >>> global >>> void One interesting way of using closure isolation is to keep state of the functions: val getAndIncrement = { // will be updated by doIt() var counter = 0 // we return callable fn from the block: fun doit() { val was = counter counter = counter + 1 was } }() // notice using of () above: it calls the lambda block that returns // a function (callable!) that we will use: println(getAndIncrement()) println(getAndIncrement()) println(getAndIncrement()) >>> 0 >>> 1 >>> 2 >>> void Inner `counter` is not accessible from outside, no way; still it is kept between calls in the closure, as inner function `doit`, returned from the block, keeps reference to it and keeps it alive. The example above could be rewritten using inner lambda, too: val getAndIncrement = { // will be updated by doIt() var counter = 0 // we return callable fn from the block: { val was = counter counter = counter + 1 was } }() // notice using of () above: it calls the lambda block that returns // a function (callable!) that we will use: println(getAndIncrement()) println(getAndIncrement()) println(getAndIncrement()) >>> 0 >>> 1 >>> 2 >>> void Lambda functions remember their scopes, so it will work the same as previous: var counter = 200 fun createLambda() { var counter = 0 { counter += 1 } } val c = createLambda() println(c) >> 1 >> void # Elements of functional programming With ellipsis and splats you can create partial functions, manipulate arguments list in almost arbitrary ways. For example: // Swap first and last arguments for call fun swap_args(first, others..., last, f) { f(last, ...others, first) } fun glue(args...) { var result = "" for( a in args ) result += a } assertEquals( "4231", swap_args( 1, 2, 3, 4, glue) ) >>> void # Annotations Annotation in Lyng resembles these proposed for Javascript. Annotation is just regular functions that, if used as annotation, are called when defining a function, var, val or class. ## Function annotation When used without params, annotation calls a function with two arguments: actual function name and callable function body. Function annotation __must return callable for the function__, either what it received as a second argument (most often), or something else. Annotation name convention is upper scaled: var annotated = false // this is annotation function: fun Special(name, body) { assertEquals("foo", name) annotated = true { body(it) + 100 } } @Special fun foo(value) { value + 1 } assert(annotated) assertEquals(111, foo( 10 )) >>> void Function annotation can have more args specified at call time. [parallelism]: parallelism.md