Jump to page: 1 2 3
Thread overview
Lambda syntax, etc
Feb 04, 2009
bearophile
Feb 04, 2009
BCS
Feb 04, 2009
Nick Sabalausky
Feb 04, 2009
Yigal Chripun
Feb 04, 2009
Nick Sabalausky
Feb 04, 2009
BCS
Feb 04, 2009
Bill Baxter
Feb 04, 2009
BCS
Feb 05, 2009
Nick Sabalausky
Feb 05, 2009
Nick Sabalausky
Feb 05, 2009
Bill Baxter
Feb 05, 2009
Bill Baxter
Feb 05, 2009
Nick Sabalausky
Feb 05, 2009
Bill Baxter
Feb 05, 2009
BCS
Feb 05, 2009
Nick Sabalausky
Feb 05, 2009
BCS
Feb 04, 2009
Yigal Chripun
Feb 05, 2009
BCS
Feb 06, 2009
Robert Fraser
Feb 04, 2009
hsyl20
Feb 05, 2009
bearophile
Feb 05, 2009
Nick Sabalausky
Feb 05, 2009
hsyl20
Feb 05, 2009
Yigal Chripun
February 04, 2009
I've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter

In Functional Java you can write this D syntax:
(int i, int j) { return i % 3 == j; }
as:
{ int i, int j => i % 3 == j }

It's shorter and less cluttered/noisy than the D syntax, and it doesn't require more type inferencing (but I think you can't put statements there, so it's less powerful).

With that Java syntax extension you can write:

final Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); final Array<Integer> b = a.filter({int i => i % 2 == 0});

In D (with dlibs) it is:

auto a = [97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42];
auto b = a.filter((int i){return !(i % 2);});

With std.algorithm it may be a bit shorter.

In Python:

a = [97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42]
b = [x for x in a if not(i % 2)]


C#2 has lambdas, and C#3 adds closures and more type inferencing, so C#3+ supports the following syntaxes:
(int i) => { return i % 3 == 1; } // C#2
i => i % 3 == 1 // C#3
i => { return i % 3 == 1; } // C#3, with statements too
To define a delegate o delegate closure:
Func<int> foo = i => { return i % 3 == 1; };
Func<int> foo = i => i % 3 == 1;
Func<int> bar = () => 2;
But this isn't allowed:
Func<void> bar = () => 2;


Few comments I have copied relative to C#3:

>C# it automatically generates either an anonymous class or an anonymous method for the closure depending on if the function needs to close over the local scope or not.<

>When such an expression is evaluated, it produces a function-object which can be called with the arguments implied by the LambdaList, and whose body expressions have access to all the lexical variables that are visible at that point. The ones that are outside of the expression, whose bindings were established before it was created, are captured. This is why the resulting object is called a LexicalClosure.<

>Even when the code uses the closure more than once, the compiler creates only one instance of the closure. That environment is reused each time.<

Bye,
bearophile
February 04, 2009
Hello bearophile,

> I've taken a look at the syntax for lambda in other C-like languages.
> This is from Functional Java:
> http://functionaljava.org/examples#Array.filter
> 
> In Functional Java you can write this D syntax:
> (int i, int j) { return i % 3 == j; }
> as:
> { int i, int j => i % 3 == j }

That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.

[...]
> i => i % 3 == 1 // C#3
> 
> i => { return i % 3 == 1; } // C#3, with statements too
> 
> To define a delegate o delegate closure:
> 
> Func<int> foo = i => { return i % 3 == 1; };
> 
> Func<int> foo = i => i % 3 == 1;
> 
> Func<int> bar = () => 2;
> 


February 04, 2009
BCS wrote:
> Hello bearophile,
> 
>> I've taken a look at the syntax for lambda in other C-like languages.
>> This is from Functional Java:
>> http://functionaljava.org/examples#Array.filter
>>
>> In Functional Java you can write this D syntax:
>> (int i, int j) { return i % 3 == j; }
>> as:
>> { int i, int j => i % 3 == j }
> 
> That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.

Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names.

Andrei
February 04, 2009
"Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:gmclr4$2q30$1@digitalmars.com...
> BCS wrote:
>> Hello bearophile,
>>
>>> I've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter
>>>
>>> In Functional Java you can write this D syntax:
>>> (int i, int j) { return i % 3 == j; }
>>> as:
>>> { int i, int j => i % 3 == j }
>>
>> That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
>
> Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names.
>
> Andrei

I would be all for the string-style, *if* things like the following were fixed:

int foo1(int i) { /*stuff*/ }
void bar(int[] ints)
{
    int foo2(int i) { /*stuff*/ }
    auto x = ints.map!("foo1(a)+foo2(a)")();
}


February 04, 2009
Andrei Alexandrescu wrote:
> BCS wrote:
>> Hello bearophile,
>>
>>> I've taken a look at the syntax for lambda in other C-like languages.
>>> This is from Functional Java:
>>> http://functionaljava.org/examples#Array.filter
>>>
>>> In Functional Java you can write this D syntax:
>>> (int i, int j) { return i % 3 == j; }
>>> as:
>>> { int i, int j => i % 3 == j }
>>
>> That syntax, and a few of the below, show the one major gripe I have
>> with ultra-compact lambdas: it's hard to *quickly* spot the args/code
>> transition.
>
> Strings are immune from the problem. :o) Also they make for readily
> recognizable code because they all use the same argument names.
>
> Andrei

Personally I prefer to have syntax for "blocks" like Ruby/smalltalk.
given the following example function:
int func(int a, delegate int(int) dg) { .. }

// call func with [something in this spirit is my favorite]:
func(someInt) { | int a, int b | return a+b; };

compare with the current D syntax:
func( someInt, (int a, int b) {return a+b;} );

compare with a lamda syntax:
func(someInt, { int a, int b => a+b } );

blocks are more useful - they are not limited to just one expression, and I think are a more general construct. lamdas/array comps, are just special cases.


February 04, 2009
"Yigal Chripun" <yigal100@gmail.com> wrote in message news:gmd0u8$fg7$1@digitalmars.com...
> Andrei Alexandrescu wrote:
>> BCS wrote:
>>> Hello bearophile,
>>>
>>>> I've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter
>>>>
>>>> In Functional Java you can write this D syntax:
>>>> (int i, int j) { return i % 3 == j; }
>>>> as:
>>>> { int i, int j => i % 3 == j }
>>>
>>> That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
>>
>> Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names.
>>
>> Andrei
>
> Personally I prefer to have syntax for "blocks" like Ruby/smalltalk.
> given the following example function:
> int func(int a, delegate int(int) dg) { .. }
>
> // call func with [something in this spirit is my favorite]: func(someInt) { | int a, int b | return a+b; };
>
> compare with the current D syntax:
> func( someInt, (int a, int b) {return a+b;} );
>
> compare with a lamda syntax:
> func(someInt, { int a, int b => a+b } );
>
> blocks are more useful - they are not limited to just one expression, and I think are a more general construct. lamdas/array comps, are just special cases.
>

Agreed. This is what I had always been ultimately hoping for. I'd be happy with the string stuff if that "wrong scope" issue gets fixed (that I mentioned in another branch of this thread), but I'd still prefer this (especially if the types for the params could somehow be inferred and omitted like this: "func(someInt) { |a,b| return a+b; };"  )



).


February 04, 2009
Reply to Nick,

> "Yigal Chripun" <yigal100@gmail.com> wrote in message
> news:gmd0u8$fg7$1@digitalmars.com...
> 
>> Andrei Alexandrescu wrote:
>> 
>>> BCS wrote:
>>> 
>>>> Hello bearophile,
>>>> 
>>>>> I've taken a look at the syntax for lambda in other C-like
>>>>> languages. This is from Functional Java:
>>>>> http://functionaljava.org/examples#Array.filter
>>>>> 
>>>>> In Functional Java you can write this D syntax:
>>>>> (int i, int j) { return i % 3 == j; }
>>>>> as:
>>>>> { int i, int j => i % 3 == j }
>>>> That syntax, and a few of the below, show the one major gripe I
>>>> have with ultra-compact lambdas: it's hard to *quickly* spot the
>>>> args/code transition.
>>>> 
>>> Strings are immune from the problem. :o) Also they make for readily
>>> recognizable code because they all use the same argument names.
>>> 
>>> Andrei
>>> 
>> Personally I prefer to have syntax for "blocks" like Ruby/smalltalk.
>> given the following example function:
>> int func(int a, delegate int(int) dg) { .. }
>> // call func with [something in this spirit is my favorite]:
>> func(someInt) { | int a, int b | return a+b; };
>> 
>> compare with the current D syntax:
>> func( someInt, (int a, int b) {return a+b;} );
>> compare with a lamda syntax:
>> func(someInt, { int a, int b => a+b } );
>> blocks are more useful - they are not limited to just one expression,
>> and I think are a more general construct. lamdas/array comps, are
>> just special cases.
>> 
> Agreed. This is what I had always been ultimately hoping for. I'd be
> happy with the string stuff if that "wrong scope" issue gets fixed
> (that I mentioned in another branch of this thread), but I'd still
> prefer this (especially if the types for the params could somehow be
> inferred and omitted like this: )
> 
> ).
> 

Why use this:

"func(someInt) { |a,b| return a+b; };"

when you can reuse syntax and get this for the same amount of typeing

"func(someInt) (a,b){ return a+b; };"


February 04, 2009
On Thu, Feb 5, 2009 at 7:26 AM, BCS <ao@pathlink.com> wrote:
> Reply to Nick,
>
>> "Yigal Chripun" <yigal100@gmail.com> wrote in message news:gmd0u8$fg7$1@digitalmars.com...
>>
>>> Andrei Alexandrescu wrote:
>>>
>>>> BCS wrote:
>>>>
>>>>> Hello bearophile,
>>>>>
>>>>>> I've taken a look at the syntax for lambda in other C-like languages. This is from Functional Java: http://functionaljava.org/examples#Array.filter
>>>>>>
>>>>>> In Functional Java you can write this D syntax:
>>>>>> (int i, int j) { return i % 3 == j; }
>>>>>> as:
>>>>>> { int i, int j => i % 3 == j }
>>>>>
>>>>> That syntax, and a few of the below, show the one major gripe I have with ultra-compact lambdas: it's hard to *quickly* spot the args/code transition.
>>>>>
>>>> Strings are immune from the problem. :o) Also they make for readily recognizable code because they all use the same argument names.
>>>>
>>>> Andrei
>>>>
>>> Personally I prefer to have syntax for "blocks" like Ruby/smalltalk.
>>> given the following example function:
>>> int func(int a, delegate int(int) dg) { .. }
>>> // call func with [something in this spirit is my favorite]:
>>> func(someInt) { | int a, int b | return a+b; };
>>>
>>> compare with the current D syntax:
>>> func( someInt, (int a, int b) {return a+b;} );
>>> compare with a lamda syntax:
>>> func(someInt, { int a, int b => a+b } );
>>> blocks are more useful - they are not limited to just one expression,
>>> and I think are a more general construct. lamdas/array comps, are
>>> just special cases.
>>>
>> Agreed. This is what I had always been ultimately hoping for. I'd be happy with the string stuff if that "wrong scope" issue gets fixed (that I mentioned in another branch of this thread), but I'd still prefer this (especially if the types for the params could somehow be inferred and omitted like this: )
>>
>> ).
>>
>
> Why use this:
>
> "func(someInt) { |a,b| return a+b; };"
>
> when you can reuse syntax and get this for the same amount of typeing
>
> "func(someInt) (a,b){ return a+b; };"

I was about to say the same thing, but I think Yigal was just mixing
two distinct suggestions together:
1) the trailing delegates proposal (aka ruby block) and
2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}

--bb
February 04, 2009
Reply to Bill,

>> I was about to say the same thing, but I think Yigal was just mixing
> two distinct suggestions together:
> 1) the trailing delegates proposal (aka ruby block) and

I like that

> 2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}

I don't like that


One #1 I'd be inclined to requier that the function be defined like

> void DoIt(int delegate(int) dg...)

D laready has this syntax for Typesafe Variadic Functions  http://www.digitalmars.com/d/1.0/function.html


February 04, 2009
Bill Baxter wrote:
> On Thu, Feb 5, 2009 at 7:26 AM, BCS<ao@pathlink.com>  wrote:
>> Reply to Nick,
>>
>>> "Yigal Chripun"<yigal100@gmail.com>  wrote in message
>>> news:gmd0u8$fg7$1@digitalmars.com...
>>>
>>>> Andrei Alexandrescu wrote:
>>>>
>>>>> BCS wrote:
>>>>>
>>>>>> Hello bearophile,
>>>>>>
>>>>>>> I've taken a look at the syntax for lambda in other C-like
>>>>>>> languages. This is from Functional Java:
>>>>>>> http://functionaljava.org/examples#Array.filter
>>>>>>>
>>>>>>> In Functional Java you can write this D syntax:
>>>>>>> (int i, int j) { return i % 3 == j; }
>>>>>>> as:
>>>>>>> { int i, int j =>  i % 3 == j }
>>>>>> That syntax, and a few of the below, show the one major gripe I
>>>>>> have with ultra-compact lambdas: it's hard to *quickly* spot the
>>>>>> args/code transition.
>>>>>>
>>>>> Strings are immune from the problem. :o) Also they make for readily
>>>>> recognizable code because they all use the same argument names.
>>>>>
>>>>> Andrei
>>>>>
>>>> Personally I prefer to have syntax for "blocks" like Ruby/smalltalk.
>>>> given the following example function:
>>>> int func(int a, delegate int(int) dg) { .. }
>>>> // call func with [something in this spirit is my favorite]:
>>>> func(someInt) { | int a, int b | return a+b; };
>>>>
>>>> compare with the current D syntax:
>>>> func( someInt, (int a, int b) {return a+b;} );
>>>> compare with a lamda syntax:
>>>> func(someInt, { int a, int b =>  a+b } );
>>>> blocks are more useful - they are not limited to just one expression,
>>>> and I think are a more general construct. lamdas/array comps, are
>>>> just special cases.
>>>>
>>> Agreed. This is what I had always been ultimately hoping for. I'd be
>>> happy with the string stuff if that "wrong scope" issue gets fixed
>>> (that I mentioned in another branch of this thread), but I'd still
>>> prefer this (especially if the types for the params could somehow be
>>> inferred and omitted like this: )
>>>
>>> ).
>>>
>> Why use this:
>>
>> "func(someInt) { |a,b| return a+b; };"
>>
>> when you can reuse syntax and get this for the same amount of typeing
>>
>> "func(someInt) (a,b){ return a+b; };"
>
> I was about to say the same thing, but I think Yigal was just mixing
> two distinct suggestions together:
> 1) the trailing delegates proposal (aka ruby block) and
> 2) A ruby-like syntax for delegate literals : {|a,b| return a+b;}
>
> --bb

not exactly. the reason why I changed the syntax like that is because of templates. for example:
void func(T, int i)(T a, delegate int(int) dg) {...}
with your and BCS' proposal the above would be called like so:

func!(SomeType, 15)(someVar)(a,b){ return a+b; };

this is less clear, IMO.

besides, I really like Ruby's (and before that Smalltalk's) syntax to handle this. <g>

to Nick -
you mentioned the scoping problem with strings. Personally I *HATE* this use of strings. it has many issues which I already mentioned in previous posts.
to specifically address your point - what your looking for is called "Hygienic Macros" - http://en.wikipedia.org/wiki/Hygienic_macros

basically you want to control which arguments to your AST macro are evaluated at which scope. This i'd like to see implemented in D when AST macros are added.
« First   ‹ Prev
1 2 3