Version 2 (modified by todd.a, 14 years ago) |
---|
Anonymous Methods/Closures? and lambdas
Cobra supports both anonymous methods (also known as closures where they capture the values of surrounding variables if referenced)
and a simpler single line expression form known as lambdas.
Both are introduced with the "do" keyword.
The syntax for closures is similar to that of the def statement (defining a classes methods) except that there is no method name.
The body of the closure follows the line the do (plus any paramList) is on, indented one level
A lambda uses the same "do" keyword as closures, but the argument list is followed by "=<expr>" all on a single line.
Grammar
Anonymous Method
do [as <Type>] # no parameters <body statements...> do(<paramList>) [as <Type>] <body statements...> For these a parameter list is a comma separated list of name (and optionally type) specifications <paramName> [as <Type>] [, ...]
Lambdas
do = <expr> # no parameters do (<paramList>) = <expr> # args passed as per invocation
Examples
Anonymous Method
sig ArithmeticOp(a as int, b as int) as int sig SimpleMethod # ... class Test def callArithmeticOp(a as int, b as int, op as ArithmeticOp) as int return op(a, b) def invoke(method as SimpleMethod) method() #... def run assert 12 == .callArithmeticOp(3, 4, do(a as int, b as int)) return a * b # multiple statements in the anonymous method assert 12 == .callArithmeticOp(3, 4, do(a as int, b as int)) r = 0 for i in a r += b assert r == a * b return r # access members assert 24 == .callArithmeticOp(3, 4, do(a as int, b as int)) return a * b * .two # access local vars multiplier = 10 assert 120 == .callArithmeticOp(3, 4, do(a as int, b as int)) return a * b * multiplier count = 0 .invoke(do) # no parameters count += 1 assert count == 1
Lambda
t = [3, 2, 1] t.sort(do(a as int, b as int)=a.compareTo(b))
Notes
The argument types are not yet inferred which is why you should specify them explicitly typed as in the examples above.
Multiple closures on a single line are not yet supported.
You can store a reference to a closure so long as you have a type for its signature. e.g
class Test def main is shared t = [3, 2, 1] # embedded closure t.sort(do(a as int, b as int)) return a.compareTo(b) # store closure in local var c as Comparison<of int> = do(a as int, b as int) return a.compareTo(b) t.sort(c)