Page 1 of 3

Anonymous methods, also known as closures

PostPosted: Sun Nov 30, 2008 1:12 am
by Charles
After working all day, these are now implemented and checked in.

Being a new feature, I'm sure we'll find a glitch or four. Let me know what you find, or if you have any questions.

What do they look like? Check out the test cases:

Tests/320-misc-two/820-anonymous-methods-aka-closures/100-anonymous-methods.cobra

Tests/320-misc-two/820-anonymous-methods-aka-closures/200-anonymous-methods-errors.cobra

Again, these well look better in your local editor than online.

Re: Anonymous methods, also known as closures

PostPosted: Sun Nov 30, 2008 2:06 am
by Kurper
How's this work with multiple closures on one line?

Re: Anonymous methods, also known as closures

PostPosted: Sun Nov 30, 2008 3:13 am
by Charles
Currently it does not. The syntax I'm contemplating is:
.foo(x, do(a is int, b as int), do(s as String))
do
return a + b
do
return s.trim.toLower

So if you have more than one anonymous method then you have a "do" for each one and put the block of code underneath that.

Feedback is welcome.

Also, how often are you encountering this with .NET libraries (whether from MS or third party)?

Re: Anonymous methods, also known as closures

PostPosted: Sun Nov 30, 2008 2:57 pm
by gauthier
That's nice!

I like the sig declaration very much but I can't say the same for the do keyword, however I can't come with something I like better according to the whitespace orientation of the language.

Could you expand on other syntax you considered and dismissed? anyone have better looking idea for the syntax?

How do you distinguish method call from method reference passing when method has no parameter? some of theses method may return closure as well...

As for passing multiple closures, the do blocks feels more natural/readable than just the indentation to me, I'm looking to use this even for single closure when it will be supported.

Re: Anonymous methods, also known as closures

PostPosted: Sun Nov 30, 2008 3:44 pm
by Charles
gauthier wrote:That's nice!

I like the sig declaration very much but I can't say the same for the do keyword, however I can't come with something I like better according to the whitespace orientation of the language.

Could you expand on other syntax you considered and dismissed? anyone have better looking idea for the syntax?

Another syntax, which is not being dismissed and will be implemented in the future, is for lambdas:
.foo(x, do(a as int, b as int) = a + b)
# general form:
... do(<args>) = <expr>

I also hope to infer the method argument types in the future (something C# does not do) so you could write:
.foo(x, do(a, b) = a + b)

Regarding dismissed syntax, originally I was planning on using the "def" keyword which is the same keyword used for declaring methods. I shied away from it because "do" reads so much better on a "listen" statement.
gauthier wrote:How do you distinguish method call from method reference passing when method has no parameter? some of theses method may return closure as well...

By prefixing with the "ref" keyword. For example, "ref .doSomething" or "ref .obj.foo.bar". I like this syntax because the "ref" immediately tips you off as to what is being done. Also, it's unambiguous. Consider this expression in Python:
obj.foo.bar

Is that a reference to a method? The answer is "maybe". If "bar" is an attribute, you get a value. If "bar" is a method, you get a method reference that is callable. If "bar" is a property, you get a value.
gauthier wrote:As for passing multiple closures, the do blocks feels more natural/readable than just the indentation to me, I'm looking to use this even for single closure when it will be supported.

Interesting; I hadn't considered doing that.

Re: Anonymous methods, also known as closures

PostPosted: Tue Dec 02, 2008 10:53 am
by helium
"Moved" from viewtopic.php?f=4&t=218#p1187

------------

Chuck wrote:-- Added anonymous methods, also known as closures.


Code: Select all
// D

void globalFunction()
{
   int x = 0;  // local variable
   void NAMED_localFunction()
   {
       printf("I can access x, I'm a closure, see: %d", x);
   }
   NAMED_localFunction();
}


Or:

Code: Select all
-- Haskell
globalFunction =
   let
      x = 0
      NAMED_localFunction = print "I can access x, I'm a closure, see: " ++ show x
   in
      NAMED_localFunction


As I explained before closures and anonymous functions are two completly unrelated things. Anonymous functions are NOT known as closures. A Closure is just a function that encloses it's scope.

And the reverse is also true: A local function - named or unnamed - doesn't necessarily have to be a closure.

Code: Select all
// D

void globalFunction()
{
   int x = 0;  // local variable
   static void NAMED_nonClosure_localFunction() // in D static makes the local function a non-closure
   {
       printf("I'm not a closure. Trying to access x woulb be a failure, as this function does not enclose its scope!");
   }
   NAMED_nonClosure_localFunction();
}

Re: Anonymous methods, also known as closures

PostPosted: Sun Dec 07, 2008 9:41 pm
by gauthier
I'm getting error while compiling this code:
class Test
def main is shared
accumulator = 0
if true
.doSomething("a".toLower.toUpper, do(i as int))
accumulator = accumulator + i
.doSomething("b", nil)
print accumulator


def doSomething(a, b as Action<of int>?) is shared
print a
if b
b(1)


Code: Select all
test.cobra(5): error: test.cobra(5,51): error: Expecting a statement instead of extra indentation. One indent level is 4 spaces or 1 tab with display width of 4.
Compilation failed - 1 error, 0 warnings


this works as expected if I remove if true and deindent the if body

also, is it possible to use closure with dynamic typing? I mean if I don't wan't to specify the method signature?

Re: Anonymous methods, also known as closures

PostPosted: Sun Dec 07, 2008 9:48 pm
by gauthier
simple question: is it possible to store a local reference of closure?

I mean like I will do with c#:
Code: Select all
Action<int> a = i => Console.WriteLine(i);
a(1);

Re: Anonymous methods, also known as closures

PostPosted: Sun Dec 07, 2008 10:59 pm
by Charles
Well we don't have lambda expressions yet, but we have anonymous methods, aka closures. And yes you can store a reference as long as you provide a type:
class Test

def main is shared
t = [1, 2, 3]

# 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)

Re: Anonymous methods, also known as closures

PostPosted: Mon Dec 08, 2008 12:13 am
by gauthier
Thanks,

I need to get better at greping the test to find out instead of asking simple questions :)

Also, it seems your sample has the same issue when adding a level of indentation (in if true block):
class Test

def main is shared
if true
t = [1, 2, 3]

# 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)



Looking forward to use theses