Kagamin wrote:
> bearophile Wrote:
>
>> 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;
>
> Yeah, C# lambdas are the killer feature. Slick, readable, C-compatible. Anders knows his job.
Without knowing the person, I disagree you could infer that from C#.
What I see above is a smörgåsbord of syntaxes that shoot all over the
proverbial barn door in the hope that one of them would strike someone's
fancy. That strikes me as a rather lousily done job. Also, it is my
perception (and not only mine) that C#'s creator completely missed the
power of templates and generative programming.
> Let's face it: delegate literals suck a little, mixins as delegates suck a lot, the former is too verbose, the latter just sucks.
The logic doesn't quite ring, but passons :o). For what it's worth
Walter has got positive feedback left and right from his talk discussing
the matter. A simplification in defining function literals is being
discussed (omitting the type from the parameters) that would simplify
template definitions considerably. Beyond that, I don't feel that
changes like moving the parameters on one side or the other of "{" would
be Earth-shattering.
Andrei

Andrei Alexandrescu>Beyond that, I don't feel that changes like moving the parameters on one side or the other of "{" would be Earth-shattering.<
As you have seen there are several possible syntaxes for anonymous functions/delegates/closures. And the current syntax already works, so I think none of such changes can be Earth-shattering.
On the other hand, extensive usage of lambdas with my dlibs has shown me that having an uncluttered and un-noisy syntax is quite important if you want to use such functional style a lot, because otherwise noise builds up quickly and in production code you are forced to split things in several lines, otherwise no one can read and debug the code you write.
Regarding such noise I can show you an almost extreme example, this is an easy programming task:
http://projecteuler.net/index.php?section=problems&id=4>Find the largest palindrome made from the product of two 3-digit numbers<
With Python:
>>> max(i*j for i in xrange(100,1000) for j in xrange(100,1000) if str(i*j) == str(i*j)[::-1])
906609
D1 with my dlibs:
import d.all;
void main() {
putr( max(select(i*j, i, xrange(100,1000), j, xrange(100,1000), str(i*j) == str(i*j).reverse)) );
}
Notice in this case Python is clearly better, not just because it's more readable, but also because that select() generates items eagerly, while the Python oneliner contains a lazy generator expression.
dlibs contain xmap too, but that code is so much more noisy that I don't want to show it :-)
I know this isn't an example of code that's normal in production, but sometimes you need extreme example to show your point :-)
Now, back to the topic: putting arguments into a single () or {} instead of a (){ return ;} (or with the => of C#) helps the eye see a single visual object isntead of two, this helps the human parsing of the code, improving visual chunking and reducing noise.
Bye,
bearophile

> What I see above is a smörgåsbord of syntaxes that shoot all over the
> proverbial barn door in the hope that one of them would strike someone's
> fancy. That strikes me as a rather lousily done job. Also, it is my
I find this statement rather ironic, because you also seem to be quite
happy with your code-as-string-literal approach. Your approach doesn't
even enforce any syntax, instead, everyone is free to invent his own.

On Thu, 05 Feb 2009 17:25:38 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> Denis Koroskin wrote:
>> On Thu, 05 Feb 2009 12:32:15 +0300, Kagamin <spam@here.lot> wrote:
>>
>>> bearophile Wrote:
>>>
>>>> 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;
>>>
>>> Yeah, C# lambdas are the killer feature. Slick, readable,
>>> C-compatible. Anders knows his job. Let's face it: delegate literals
>>> suck a little, mixins as delegates suck a lot, the former is too
>>> verbose, the latter just sucks.
>> I don't like C# lambda syntax (although it is not half as bad as C++
>> lambda syntax).
>> I believe D delegate syntax is superior due to its natural and
>> unambiguous syntax.
>> But yes, it could be made shorter by improving type deduction:
>> int delegate(int) inc = (i) { i + 1; }
>> Which would be the same as
>> int delegate(int) inc = (int i) { return i + 1; }
>
> What if you wanted to just execute one expression and return void? This
> is relevant when e.g. large objects are involved that shouldn't be
> copied unwittingly.
>
No problem:
void delegate(int) inc = (i) { i + 1; };
which would be transformed into
void delegate(int) inc = (int i) { i + 1; };
or
void delegate(int) inc = (int i) { return i + 1; };
Both are valid D code according to specs[1].
The second one doesn't compile as of now, but this is a DMD bug, I assume.
>> where i's type is deduced from inc's type and the only expression (i +
>> 1) made a return value:
>> auto x = inc(5); // yields 6
>> Here is an another example:
>> void foo(void delegate(ref int i) inc);
>> Could be used as follows:
>> foo( (i) { ++i; } );
>> as opposed to
>> foo( (ref int i) { ++i; } );
>
> Aha! So here you are using a void-returning function. Now what if there
> was another overload of foo in place:
>
> void foo(int delegate(ref int i) inc);
>
> Which foo is to be called? The one that infers a return type of int or
> the one that assumes the code just returns void?
>
1) Compiler can flag an ambiguity error at compile time so that user resolve it:
foo((i){ ++i; }); // error
foo((i){ ++i; return;}); // unambiguous
foo((i){ return ++i;}); // unambiguous
2) (The one I prefer) Make (i) { ++i; } return int. The following could be used to force void return type:
foo((i){ ++i;; }); // note the double semicolon.
It returns void for two reasons:
a) second ; evaluates to void
b) it is not a single-statement delegate anymore.
Implicit return should only be allowed for single statement delegates that are very frequently used (mostly as a predicate) and almost never return void.
I doubt it will lead to errors. The very example is rather artificial.
>> I can put this enhancement request into bugzilla if anyone likes it.
>
> It would be great to add the parameter type deduction stuff; that is
> already talked about and doesn't seem to have many issues. It does have
> one, which I'm sure people here will see rather quickly.
>
>
> Andrei
---
[1]statement.html:
ReturnStatement:
return;
return Expression;
Expression is allowed even if the function specifies a void return type. The Expression will be evaluated, but nothing will be returned.

grauzone wrote:
>> What I see above is a smörgåsbord of syntaxes that shoot all over the
>> proverbial barn door in the hope that one of them would strike
>> someone's fancy. That strikes me as a rather lousily done job. Also,
>> it is my
>
> I find this statement rather ironic, because you also seem to be quite
> happy with your code-as-string-literal approach.
I do understand you dislike strings as lambdas, but please do not use
that dislike as a presupposition of a truth.
Besides, there is no correlation. D offers two syntaxes, a decent lambda
syntax (that is being improved) and a string syntax for short
predicates. They have clear and distinct tradeoffs and charters. In
contrast, C# seems to have decided to allow pretty much all syntax
variations that parse unambiguously. You can only wonder what C#4 has in
store.
> Your approach doesn't
> even enforce any syntax, instead, everyone is free to invent his own.
There's only so many ways to write an expression involving one or two
given symbols.
Andrei

Reply to Andrei,
> Kagamin wrote:
>
> Also,
> it is my perception (and not only mine) that C#'s creator completely
> missed the power of templates and generative programming.
>
I have never met the man, but it is my impression that Anders didn't miss
the power, he just doesn't care for the paradigm. I would speculate that
because there is nothing that it adds that can't be done at runtime (ignoring
things like perf), he left it out. C# seems to take the "do stuff as late
as you can" approach across the board.