| OLD | NEW |
| 1 --- | 1 --- |
| 2 layout: default | 2 layout: default |
| 3 title: "Emulating Functions in Dart" | 3 title: "Emulating Functions in Dart" |
| 4 rel: | 4 rel: |
| 5 author: gilad-bracha | 5 author: gilad-bracha |
| 6 --- | 6 --- |
| 7 | 7 |
| 8 <h1> {{ page.title }}</h1> | 8 <h1> {{ page.title }}</h1> |
| 9 <em>Written by Gilad Bracha <br /> | 9 <em>Written by Gilad Bracha <br /> |
| 10 January 2012</em> | 10 January 2012</em> |
| 11 | 11 |
| 12 <section> | 12 <section> |
| 13 <p> | 13 <p> |
| 14 This document describes a refinement of the Dart programming language | 14 This document describes a refinement of the Dart programming language |
| 15 that allows user-defined classes that are substitutable for functions. | 15 that allows user-defined classes that are substitutable for functions. |
| 16 </p> | 16 </p> |
| 17 | 17 |
| 18 <aside class="note"> | 18 <aside> |
| 19 <b>Note:</b> | 19 <div class="alert alert-info"> |
| 20 This functionality is <b>not yet implemented</b>, | 20 <strong>Note:</strong> |
| 21 but is specified as part of version 0.07 of the | 21 This functionality is <b>not yet implemented</b>, |
| 22 <a href="http://www.dartlang.org/docs/spec/index.html">Dart | 22 but is specified as part of version 0.07 of the |
| 23 Programming Language Specification</a>. | 23 <a href="http://www.dartlang.org/docs/spec/index.html">Dart |
| 24 Hopefully it will find its way into our implementations in due course, | 24 Programming Language Specification</a>. |
| 25 though it may be quite a while. | 25 Hopefully it will find its way into our implementations in due course, |
| 26 though it may be quite a while. |
| 27 </div> |
| 26 </aside> | 28 </aside> |
| 27 | 29 |
| 28 <section class="toc"> | 30 <section class="toc"> |
| 29 <h4>Contents</h4> | 31 <h4>Contents</h4> |
| 30 <ol class="toc"> | 32 <ol class="toc"> |
| 31 <li> <a href="#call">The call operator</a> </li> | 33 <li> <a href="#call">The call operator</a> </li> |
| 32 <li> <a href="#apply">The Function interface and apply() method</a> </li> | 34 <li> <a href="#apply">The Function interface and apply() method</a> </li> |
| 33 <li> <a href="#types">Function types</a> </li> | 35 <li> <a href="#types">Function types</a> </li> |
| 34 <li> <a href="#nosuchmethod">Interactions with noSuchMethod()</a> </li> | 36 <li> <a href="#nosuchmethod">Interactions with noSuchMethod()</a> </li> |
| 35 <li> <a href="#summary">Summary</a> </li> | 37 <li> <a href="#summary">Summary</a> </li> |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 If <code>x</code> supports a <b>call</b> operator with suitable arguments | 71 If <code>x</code> supports a <b>call</b> operator with suitable arguments |
| 70 it gets called. | 72 it gets called. |
| 71 Otherwise, <code>noSuchMethod()</code> | 73 Otherwise, <code>noSuchMethod()</code> |
| 72 (defined by <code>Object</code>) is called. | 74 (defined by <code>Object</code>) is called. |
| 73 The default implementation of <code>noSuchMethod()</code> checks to see | 75 The default implementation of <code>noSuchMethod()</code> checks to see |
| 74 whether it was called for method name <b>call</b>, | 76 whether it was called for method name <b>call</b>, |
| 75 and if so issues a helpful error message suggesting | 77 and if so issues a helpful error message suggesting |
| 76 you might have wanted to use a closure. | 78 you might have wanted to use a closure. |
| 77 </p> | 79 </p> |
| 78 | 80 |
| 79 <aside class="note"> | 81 <p> |
| 80 <b>Side note:</b> | |
| 81 Why do we insist on <b>call</b>? It might seem like | 82 Why do we insist on <b>call</b>? It might seem like |
| 82 | 83 |
| 83 <pre>operator () (int a) => a *2;</pre> | 84 <pre>operator () (int a) => a *2;</pre> |
| 84 | 85 |
| 85 could work instead of | 86 could work instead of |
| 86 | 87 |
| 87 <pre>operator call (int a) => a * 2;</pre> | 88 <pre>operator call (int a) => a * 2;</pre> |
| 88 | 89 |
| 89 However, as shown below, | 90 However, as shown below, |
| 90 we need to be able to closurize the operator | 91 we need to be able to closurize the operator |
| 91 (for example, <code>f.call</code>), which doesn’t work for <b>()</b>. | 92 (for example, <code>f.call</code>), which doesn’t work for <b>()</b>. |
| 92 (We don’t allow <code>f.()</code>. | 93 (We don’t allow <code>f.()</code>. |
| 93 It is clearly too error prone.) | 94 It is clearly too error prone.) |
| 94 </aside> | 95 </p> |
| 95 | 96 |
| 96 <section> | 97 <section> |
| 97 <h2 id="apply"> The Function interface and apply() method </h2> | 98 <h2 id="apply"> The Function interface and apply() method </h2> |
| 98 | 99 |
| 99 <p> | 100 <p> |
| 100 Actual function objects have an <code>apply()</code> method | 101 Actual function objects have an <code>apply()</code> method |
| 101 whose signature is defined in the <code>Function</code> interface as: | 102 whose signature is defined in the <code>Function</code> interface as: |
| 102 </p> | 103 </p> |
| 103 | 104 |
| 104 {% highlight dart %} | 105 {% highlight dart %} |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 It is always possible to invoke such an object <code>f</code> | 149 It is always possible to invoke such an object <code>f</code> |
| 149 as a function using an <code>ArgumentDescriptor</code> | 150 as a function using an <code>ArgumentDescriptor</code> |
| 150 by closurizing its <code>call</code> method | 151 by closurizing its <code>call</code> method |
| 151 and calling <code><code>apply()</code></code> on it: | 152 and calling <code><code>apply()</code></code> on it: |
| 152 </p> | 153 </p> |
| 153 | 154 |
| 154 {% highlight dart %} | 155 {% highlight dart %} |
| 155 f.call.apply(args); | 156 f.call.apply(args); |
| 156 {% endhighlight %} | 157 {% endhighlight %} |
| 157 <br> | 158 <br> |
| 158 <aside class="note"> | 159 |
| 159 <b>Side note:</b> | 160 <p> |
| 160 We could say that if you declare operator <b>call</b>, | 161 We could say that if you declare operator <b>call</b>, |
| 161 <code>apply()</code> gets created for you. | 162 <code>apply()</code> gets created for you. |
| 162 However, this entails an undesirable degree of magic. | 163 However, this entails an undesirable degree of magic. |
| 163 One has to deal with interactions with | 164 One has to deal with interactions with |
| 164 user-defined <code>apply()</code> methods, | 165 user-defined <code>apply()</code> methods, |
| 165 whether locally declared or (worse) inherited. | 166 whether locally declared or (worse) inherited. |
| 166 Debuggers need to know how to display | 167 Debuggers need to know how to display |
| 167 these synthetic <code>apply()</code> methods, | 168 these synthetic <code>apply()</code> methods, |
| 168 and so on. | 169 and so on. |
| 169 </aside> | 170 </p> |
| 170 </section> | 171 </section> |
| 171 | 172 |
| 172 <section> | 173 <section> |
| 173 <h2 id="types"> Function types </h2> | 174 <h2 id="types"> Function types </h2> |
| 174 | 175 |
| 175 <p> | 176 <p> |
| 176 An additional issue is how | 177 An additional issue is how |
| 177 user-defined function classes relate to the type system. | 178 user-defined function classes relate to the type system. |
| 178 To simulate functions properly, | 179 To simulate functions properly, |
| 179 we want them to be members of the appropriate function type: | 180 we want them to be members of the appropriate function type: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 (in this case, the result of <code>bar()</code>). | 216 (in this case, the result of <code>bar()</code>). |
| 216 The third line handles the case where you want to forward | 217 The third line handles the case where you want to forward |
| 217 just the parameters to another function. | 218 just the parameters to another function. |
| 218 If <code>baz</code> doesn't implement | 219 If <code>baz</code> doesn't implement |
| 219 <code>Function</code> and <code>apply()</code> | 220 <code>Function</code> and <code>apply()</code> |
| 220 as we recommended above, | 221 as we recommended above, |
| 221 then that code should instead be | 222 then that code should instead be |
| 222 <code>baz.<b>call.</b>apply(msg.arguments)</code>. | 223 <code>baz.<b>call.</b>apply(msg.arguments)</code>. |
| 223 </p> | 224 </p> |
| 224 | 225 |
| 225 <aside class="note"> | 226 <p> |
| 226 <b>Side note:</b> | |
| 227 The only argument to <code>noSuchMethod()</code> | 227 The only argument to <code>noSuchMethod()</code> |
| 228 is an <code>InvocationMirror</code>, | 228 is an <code>InvocationMirror</code>, |
| 229 which is currently defined as follows: | 229 which is currently defined as follows: |
| 230 </p> |
| 230 | 231 |
| 231 {% highlight dart %} | 232 {% highlight dart %} |
| 232 interface InvocationMirror { | 233 interface InvocationMirror { |
| 233 | 234 |
| 234 final String memberName; | 235 final String memberName; |
| 235 final ArgumentDescriptor arguments; | 236 final ArgumentDescriptor arguments; |
| 236 final bool isGetter; | 237 final bool isGetter; |
| 237 final bool isSetter; | 238 final bool isSetter; |
| 238 final bool isMethod; | 239 final bool isMethod; |
| 239 final bool isAccessor; | 240 final bool isAccessor; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 <p> | 294 <p> |
| 294 It is important not to assume that <code>isMethod</code> means | 295 It is important not to assume that <code>isMethod</code> means |
| 295 that a non-accessor was being looked up, | 296 that a non-accessor was being looked up, |
| 296 since in fact, Dart semantics mean | 297 since in fact, Dart semantics mean |
| 297 that we would have called <code>noSuchMethod()</code> only if | 298 that we would have called <code>noSuchMethod()</code> only if |
| 298 neither a normal method nor a getter were found. | 299 neither a normal method nor a getter were found. |
| 299 Likewise, <code>isGetter</code> does not imply a getter was being looked up; | 300 Likewise, <code>isGetter</code> does not imply a getter was being looked up; |
| 300 if a method was present, | 301 if a method was present, |
| 301 it would be closurized and returned. | 302 it would be closurized and returned. |
| 302 </p> | 303 </p> |
| 303 </aside> | 304 |
| 304 </section> | 305 </section> |
| 305 | 306 |
| 306 | 307 |
| 307 <section> | 308 <section> |
| 308 <h2 id="summary">Summary</h2> | 309 <h2 id="summary">Summary</h2> |
| 309 | 310 |
| 310 <p> | 311 <p> |
| 311 The ability to declare user-defined classes whose instances can be | 312 The ability to declare user-defined classes whose instances can be |
| 312 treated like ordinary functions is coming to Dart. | 313 treated like ordinary functions is coming to Dart. |
| 313 It isn’t implemented yet, | 314 It isn’t implemented yet, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 {% highlight dart %} | 346 {% highlight dart %} |
| 346 apply(args) => this.call.apply(args); | 347 apply(args) => this.call.apply(args); |
| 347 {% endhighlight %} | 348 {% endhighlight %} |
| 348 </li> | 349 </li> |
| 349 </ol> | 350 </ol> |
| 350 </section> | 351 </section> |
| 351 | 352 |
| 352 </section> | 353 </section> |
| 353 | 354 |
| 354 | 355 |
| OLD | NEW |