tag:blogger.com,1999:blog-741750605858169835.post2355738756657694706..comments2024-01-24T14:53:02.919+00:00Comments on Stephen Colebourne's blog: Closures - Control-invocation syntaxStephen Colebournehttp://www.blogger.com/profile/01454237967846880639noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-741750605858169835.post-89152315710229919002007-01-23T00:35:08.000+00:002007-01-23T00:35:08.000+00:00"Made the hair on the back of my neck stand u..."Made the hair on the back of my neck stand up."<br /><br />I hope thats a good thing ;-)Stephen Colebournenoreply@blogger.comtag:blogger.com,1999:blog-741750605858169835.post-69703871162302036242007-01-22T23:43:39.000+00:002007-01-22T23:43:39.000+00:00"Secondly, lets allow the closure-control-met..."Secondly, lets allow the closure-control-method to return a result, but without being an expression, and without requiring the semicolon."<br /><br />Wow! Now I got it!<br /><br />Made the hair on the back of my neck stand up.Tiago Silveirahttp://jroller.com/page/dukejeffrienoreply@blogger.comtag:blogger.com,1999:blog-741750605858169835.post-9005759570356279662007-01-22T10:50:44.000+00:002007-01-22T10:50:44.000+00:00@Stephen: It's similar wrt. the control invoca...@Stephen: It's similar wrt. the control invocation syntax. The closure infix uses the fat arrow already to seperate the closure argument definitions from the closure block, which would conflict with using the arrow for returning a value. That's what I tried to capture in a consistent way. Unfortunately, as Neal referenced, there is no way for having a generic return value statement.<br /><br />To the terminal Symbol, I actually didn't think much about the notation but rather needed some way to describe the idea. I borrowed the syntax for describing temporary/local block variables in Smalltalk and took symbol that does not conflict with the FunctionType definition and still reminds of the assignment. <br />In general, it's nothing but a typed label put on the closure.Stefan Schulznoreply@blogger.comtag:blogger.com,1999:blog-741750605858169835.post-88933600287387976842007-01-22T00:22:21.000+00:002007-01-22T00:22:21.000+00:00@Stefan, In your first comment you changed the def...@Stefan, In your first comment you changed the definition syntax but ended up with the same usage syntax as I'm proposing. I don't believe that the current BGGA definition syntax needs to change at all to achieve the usage syntax I'm suggesting with a => operator meaning 'resulting in'.<br /><br />Your second proposal is not unlike one possibility I've considered before. It definitely identifies the closure to return to which is a good thing. I'm not sure that exact syntax looks good though.<br /><br />@Ricky, I said in the last post that for a single expression closure-block, there is no need for two => operators immediately after one another - they merge into one (thats why I'm using =>). This fits with the single line style.<br /><br />And we are not that far apart on the actual format either, as compared to your example, I'm asking for:<br /><br />List[String] onlySmiths = filter(String name:names) {<br />' => name.contains("Smith");<br />}Stephen Colebournenoreply@blogger.comtag:blogger.com,1999:blog-741750605858169835.post-5593622506284587022007-01-21T22:55:19.000+00:002007-01-21T22:55:19.000+00:00@Neal: Thanks for that reference. So I understood,...@Neal: Thanks for that reference. So I understood, that the problem would be for (somehow) nested returns (or ^ or =>) and, maybe, too, for break and continue? I think, that thinking closures may be quite unsatisfying sometimes ;)<br /><br />Having a closure's value being the value of the last statement within the closure is actually the same as in Smalltalk, so I should not wonder. But in general, the problem seems to be having a generic return statement.<br /><br />So for returning a value, one would, for example, define a temporary variable, which will be used as last statement in the closure. Maybe it would make things clearer, if a return variable can be defined that will be used to identify the return value of the closure that is the scope of this variable. And as markup that the assigment will end the closure immediately, use =| instead of = (looking like a terminal symbol to not conflict with FunctionType-Definitions). Somewhat like follows:<br /><br />List matches = findAll(Booking booking : bookingList) { <br />´ | boolean foundOne |<br />´ for (Purchase purchase : booking.getPurchases()) {<br />´ ´ if (purchase.contains(typeToFind)) {<br />´ ´ ´ foundOne =| true;<br />´ ´ }<br />´ }<br />´ foundOne =| false;<br />}<br /><br />Hiding names would be easy to identify and nested closures can use seperate names as for arguments.<br /><br />@Ricky: That's why I changed the => to point to the return value not the closure body and have the closures arguments defined as one is used to for methods: using parentheses. Which would also be consistent with defining FunctionTypes, btw.Stefan Schulznoreply@blogger.comtag:blogger.com,1999:blog-741750605858169835.post-53353582715234169892007-01-21T22:29:30.000+00:002007-01-21T22:29:30.000+00:00Further to Neal's comment, the spec already us...Further to Neal's comment, the spec already uses => to denote the start of a closure body, therefore using it for a return value would be odd - would you have two => symbols in a multi-statement closure?<br /><br />I'd prefer one syntax, the 'statement' form, for both statement and expression closures. E.g.:<br /><br />List[String] onlySmiths=filter(String name:names)<br />{<br /> name.contains("Smith")<br />};<br /><br />For the above, I don't think last-line-no-semi-colon is a bad thing. Neal says that the issue is that there's a semi-colon at the end of that, but I'm not sure why that's an issue; in a statement context, don't require a semi-colon. Otherwise, do. Perhaps there's something subtle I can't see here.Ricky Clarksonhttp://cime.net/~ricky/noreply@blogger.comtag:blogger.com,1999:blog-741750605858169835.post-86417330998421173122007-01-21T19:52:42.000+00:002007-01-21T19:52:42.000+00:00Stefan: the reason we don't allow this is expl...Stefan: the reason we don't allow this is explained here: http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.htmlNeal Gafterhttp://gafter.blogspot.comnoreply@blogger.comtag:blogger.com,1999:blog-741750605858169835.post-31292979600464440982007-01-21T18:57:04.000+00:002007-01-21T18:57:04.000+00:00I'm not sure, where to put this (too many Clos...I'm not sure, where to put this (too many Closure-posts), hence I will take the latest. Instead of poking around with return, why not change the proposal's syntax for defining closures and function types slightly to allow for returning values by using a different keyword or key symbol? In the current proposal there already is such a symbol: a fat arrow. Although, I would rather like a keyword (e.g., yield), the => sign seems shorter and more welcome for some people.<br /><br />Below I wrote down the current style in BGGA and a modified variant with several examples, which makes the => symbol to become a Closure-Yield. I'm not sure whether it becomes less readable or less Java-ish or more difficult to parse. The only change I made is dropping some curly braces, adding some parens and shifting the fat arrow.<br /><br />=== BGGA proposed style (° = opt) ===<br />Closure:<br />´ { FormalParameterDecls° => BlockStatements° Expression° }<br />FunctionType:<br />´ { Types° => Type Throws° }<br /><br />Example:<br />{int=>int} plus2 = {int x => x+2};<br /><br />=== Modified style (° = opt) ===<br />Closure:<br />´ ( FormalParameterDecls° ) { Statements° }<br />Statements:<br />´ Statement; Statements°<br />Statement:<br />´ BlockStatement<br />´ => Expression<br />(Not sure, how to denote that the usage of => follows the same rules than return in a method.)<br />FunctionType:<br />´ ( Types° ) => Type Throws°<br /><br />Definitions:<br />(int) => int plus2 = (int x) => x+2;<br /> (List, T) => boolean contains = (List list, T match) {<br />´ for (T t : list) {<br />´ ´ if (match.equals(t)) => true;<br />´ }<br />´ => false;<br />}<br /> (List, (T) => boolean) => List findAll = (List list, (T) => boolean condition) {<br />´ List matches = new ArrayList();<br />´ for (T t : list) {<br />´ ´ if (condition.invoke(t)) {<br />´ ´ ´ matches.add(t);<br />´ ´ }<br />´ }<br />´ => matches;<br />}<br /><br />Usages:<br />i = plus2(j);<br />b = contains(names, "Neal");<br />// argument style<br />List matches = findAll(bookingList, (Booking booking) {<br />´ for (Purchase purchase : booking.getPurchases()) {<br />´ ´ if (purchase.contains(typeToFind)) {<br />´ ´ ´ => true;<br />´ ´ }<br />´ }<br />´ => false;<br />});<br />// control invocation style<br />List matches = findAll(Booking booking : bookingList) {<br />´ for (Purchase purchase : booking.getPurchases()) {<br />´ ´ if (purchase.contains(typeToFind)) {<br />´ ´ ´ => true;<br />´ ´ }<br />´ }<br />´ => false;<br />}Stefan Schulznoreply@blogger.com