| 1 | = Delegates = |
| 2 | |
| 3 | (also known as typesafe (function) method pointers). |
| 4 | |
| 5 | A delegate is a type that safely encapsulates a method of a specific signature |
| 6 | (method return type and parameters). |
| 7 | |
| 8 | A reference to any method that matches the delegate's signature |
| 9 | can be assigned to the delegate. |
| 10 | |
| 11 | Once a delegate is assigned a method, it behaves exactly like that method |
| 12 | and can be used like any other method, with parameters and |
| 13 | a return value. |
| 14 | |
| 15 | The type of a delegate is defined by the name of the delegate. |
| 16 | |
| 17 | In cobra, delegates are declared as "method signatures" and define a type: |
| 18 | e.g |
| 19 | {{{ |
| 20 | sig FunctionWithOneIntArgAndReturnsBool(i as int32) as bool |
| 21 | }}} |
| 22 | |
| 23 | Here the delegate type name is "!FunctionWithOneIntArgAndReturnsBool" |
| 24 | |
| 25 | The following is the usual set of steps in declaring a delegate type, a conforming method and instantiating and |
| 26 | invoking the delegate. |
| 27 | {{{ |
| 28 | # The following declares a delegate (type) named Del that can |
| 29 | #encapsulate a method that takes a string as an argument and returns void: |
| 30 | sig Del(message as String) |
| 31 | ... |
| 32 | # a method that conforms to the delegate Type |
| 33 | def delegateMethod(msg as String) |
| 34 | Console.writeline(msg) |
| 35 | ... |
| 36 | |
| 37 | # Instantiate the delegate. |
| 38 | handler as Del = .ref delegateMethod |
| 39 | |
| 40 | # invoke the delegate. |
| 41 | handler("Hello World"); |
| 42 | }}} |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | == Grammar == |
| 48 | {{{ |
| 49 | # delegate definition |
| 50 | sig TYPENAME(ARGS) as TYPE |
| 51 | |
| 52 | # delegate instantiation |
| 53 | name as SIGTYPENAME = ref METHODNAME |
| 54 | |
| 55 | # delegate invocation |
| 56 | name # no arg delegate |
| 57 | name(ARGS) |
| 58 | }}} |
| 59 | |
| 60 | |
| 61 | == Examples == |
| 62 | {{{ |
| 63 | class SigEG |
| 64 | sig IntTest(i as int) as bool |
| 65 | |
| 66 | def tstInt( i as int) as bool is shared |
| 67 | return i > 47 |
| 68 | |
| 69 | def main is shared |
| 70 | tester as IntTest = ref .tstInt |
| 71 | assert tester(99) |
| 72 | assert not tester(3) |
| 73 | }}} |
| 74 | |
| 75 | {{{ |
| 76 | # as above using an anon function |
| 77 | tester as IntTest = do(i as int) |
| 78 | return i > 47 |
| 79 | |
| 80 | assert tester(99) |
| 81 | assert not tester(3) |
| 82 | |
| 83 | # using a lambda expression |
| 84 | tester = do(i as int) = i > 100 |
| 85 | assert not tester(99) |
| 86 | assert tester(103) |
| 87 | }}} |
| 88 | |
| 89 | == Notes == |
| 90 | |
| 91 | Type inference on delegate variables and method references is not all it could be |
| 92 | so currently delegate variable definitions need a type definition. |
| 93 | {{{ |
| 94 | name as SIGTYPENAME = ref METHOD |
| 95 | # rather than just |
| 96 | name = ref METHOD |
| 97 | }}} |