Wiki

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 (resolution of ticket:204) 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)