December 07, 2009
Mon, 07 Dec 2009 16:19:37 +0100, klickverbot wrote:

> Denis Koroskin wrote:
>> Although I believe it is implementable and worth the trouble, there is a little gain in this feature and that's probably why it is low in the list. I think that Walter will give a green light if someone implements the feature and provides a complete patch.
>> 
>> Any volunteers?
> 
> If someone should step forward to implement this: I would really like to be able to omit the semicolon inside one-statement delegates/lambdas. It makes using them feel much more natural (at least to me) – just look at some Ruby code.

I think the counterargument was: semicolons help spotting bugs everywhere since the parser immediately sees this as syntax error.
December 07, 2009
Leandro Lucarella wrote:
> Michal Minich, el  7 de diciembre a las 13:51 me escribiste:
>> Hello Denis,
>>
>>>> 1. auto t = new Thread ( { a=42 } );
>>>> or auto t = new Thread ( () { a=42 } );
>>> It already works, just try it (but don't forget to put a semicolon at
>>> the  end).
>>>
>>>> 2. array.findAll (arr, (item) { item.contains ("abc") } ); 3. foo (
>>>> (a, b) { a + b } );
>>>>
>>>> 4. array.findAll (arr, (item) { return item.contains ("abc"); } );
>>>>
>>>> I'm not proposing this syntax (maybe I probably should, but I have
>>>> feeling I would not be first). It may not even be possible to parse
>>>> it,  but seems to me more similar to how currently functions are
>>>> written. In  this setting {exp} or {stm} is not *special* case.
>>>>
>>> I believe it would work. And yes, it was already proposed by many
>>> others.
>>>
>> it works with two differences:
>>
>> 1. the semicolon is required, even if the body consist only of one
>> expression. This is a minor detail.
>> 2. more importantly - parameter types must be specified explicitly.
>> I don't understand why type of b cannot be inferred in this example:
>>
>> void foo (void delegate (int a) dg)
>> {
>>    dg(1);
>> }
>>
>> void main ()
>> {
>>    foo ( (int b)  { writeln (b); } );
>> }
> 
> It doesn't do implicit returning either:
> 
> $ cat -n x.d
>      1	
>      2	import std.stdio;
>      3	
>      4	void foo (int delegate() dg)
>      5	{
>      6		writeln(dg());
>      7	}
>      8	
>      9	void main()
>     10	{
>     11		int a = 5;
>     12		foo({a;});
>     13	}
>     14	
> $ dmd x.d
> x.d(12): Error: var has no effect in expression (a)
> x.d(12): Error: function x.foo (int delegate() dg) is not callable using argument types (void delegate())
> x.d(12): Error: cannot implicitly convert expression (__dgliteral1) of type void delegate() to int delegate()
> 
> To make it work you have to do it like this:
>     12		foo({return a;});
> 
> Which is considerably uglier than
>     12		foo({a});
> 
> At least when talking about replacing "lazy" :)
> 
> Nobody wants to write:
> enforce({ return a == 5; });
> instead of:
> enforce(a == 5);
> 
> But:
> enforce({a == 5});
> 
> Could be acceptable.

A nit - it's the second argument of enforce that must be lazy, e.g.

enforce(a == 5, {return text("a is not 5, it's ", a);});

Not looking good anyway.


Andrei
December 07, 2009
retard wrote:
> Mon, 07 Dec 2009 13:17:10 +0000, Michal Minich wrote:
> 
>> Hello bearophile,
>>
>>> Michal Minich:
>>>
>>>> But introduction "{ epx }" as delegate/function literal for functions
>>>> with no arguments, which implicitly returns result of the expression,
>>>> seems to me as a good idea.
>>>>
>>> It's a special case, and special cases help to kill languages. It's not
>>> important enough.
>>> But a general shorter syntax for lambdas is possible, like the C# one.
>>> Evaluations lazy arguments only 0 or 1 times sounds like a nice idea.
>>> Bye,
>>> bearophile
>> Yes, it works well in C#, and it is one of the best extension of this
>> language (only adding generics was better).
>>
>> Consider how it works in C#, and how it could in D
>>
>> // 1. lambda with no parameter
>> int a;
>> var t = new Thread (  () => a=42  );
>>
>> // 2. lambda with one parameter
>> string[] arr;
>> Array.FindAll (arr, item => item.Contains ("abc"));
>>           // 3. lambda with more parameters
>> Foo (  (a, b) => a + b );
> 
> You surely understand that Walter doesn't have enough time to change this before the Andrei's book is out. So D2 won't be getting this. Besides, he hasn't even said that he likes the syntax. And D can't infer the types that way, you would need
> 
>> Foo (  (auto a, auto b) => a + b );
> 
> or
> 
>> Foo (  [T,S](T a, S b) => a + b );
> 
>> // 4. lambda with statement (previous examples were expressions)
>> Array.FindAll (arr, item =>  { return item.Contains ("abc"); } ); //
>> curly braces, semicolon and return are required when statement is used.
>>
>> D could use:
>>
>> 1. auto t = new Thread ( { a=42 } );
>> or auto t = new Thread ( () { a=42 } );
>>
>> 2. array.findAll (arr, (item) { item.contains ("abc") } );
> 
> Andrei invented the string template parameter hack to avoid this. This would work too slowly since the dmd backend from the 1960s cannot inline anonymous functions. It can only inline named functions.
> 
>>           3. foo ( (a, b) { a + b } );
>>
>> 4. array.findAll (arr, (item) { return item.contains ("abc"); } );
>>
>> I'm not proposing this syntax (maybe I probably should, but I have
>> feeling I would not be first). It may not even be possible to parse it,
>> but seems to me more similar to how currently functions are written. In
>> this setting {exp} or {stm} is not *special* case.
> 
Actually, it can, and will, infer the types for (a, b) { ... }

It not doing so right now is on the bugzilla.
December 08, 2009
retard wrote:
...
> You surely understand that Walter doesn't have enough time to change this before the Andrei's book is out. So D2 won't be getting this. Besides, he hasn't even said that he likes the syntax. And D can't infer the types that way, you would need
> 
>> Foo (  (auto a, auto b) => a + b );

why not ? (a, b) { return a +  b; } already works for template alias
parameters.

> or
> 
>> Foo (  [T,S](T a, S b) => a + b );
> 
>> 
>> // 4. lambda with statement (previous examples were expressions)
>> Array.FindAll (arr, item =>  { return item.Contains ("abc"); } ); //
>> curly braces, semicolon and return are required when statement is used.
>> 
>> D could use:
>> 
>> 1. auto t = new Thread ( { a=42 } );
>> or auto t = new Thread ( () { a=42 } );
>> 
>> 2. array.findAll (arr, (item) { item.contains ("abc") } );
> 
> Andrei invented the string template parameter hack to avoid this. This would work too slowly since the dmd backend from the 1960s cannot inline anonymous functions. It can only inline named functions.
> 

I don't think inlining is done in the backend.

December 08, 2009
Tue, 08 Dec 2009 01:02:04 +0100, Lutger wrote:

> retard wrote:
> ...
>> You surely understand that Walter doesn't have enough time to change this before the Andrei's book is out. So D2 won't be getting this. Besides, he hasn't even said that he likes the syntax. And D can't infer the types that way, you would need
>> 
>>> Foo (  (auto a, auto b) => a + b );
> 
> why not ? (a, b) { return a +  b; } already works for template alias
> parameters.
> 
>> or
>> 
>>> Foo (  [T,S](T a, S b) => a + b );
>> 
>> 
>>> // 4. lambda with statement (previous examples were expressions)
>>> Array.FindAll (arr, item =>  { return item.Contains ("abc"); } ); //
>>> curly braces, semicolon and return are required when statement is
>>> used.
>>> 
>>> D could use:
>>> 
>>> 1. auto t = new Thread ( { a=42 } );
>>> or auto t = new Thread ( () { a=42 } );
>>> 
>>> 2. array.findAll (arr, (item) { item.contains ("abc") } );
>> 
>> Andrei invented the string template parameter hack to avoid this. This would work too slowly since the dmd backend from the 1960s cannot inline anonymous functions. It can only inline named functions.
>> 
>> 
> I don't think inlining is done in the backend.

Nope, but it isn't done in other parts of the compiler, either, for that matter.
December 08, 2009
Hello Andrei,

> Michal Minich wrote:
> 
>> Hello Andrei,
>> 
>>> Should we sack lazy? I'd like it to have a reasonable replacement.
>>> Ideas are welcome!
>>> 
>>> Andrei
>>> 
>> there are 3 sides from which to look at lazy function parameter.
>> 
>> 1. Usage - being able to send expressions to function is very
>> important for writing clear and nice looking code. I think just by
>> requiring enclosure in curly braces "fun({gun();})" would make this
>> feature quite less appealing and used. This syntactic feature is very
>> pleasing - by whichever feature at definition side it is achieved
>> (macro/expression type), it should stay here.
>> 
> I think the same. But I seem to recall that at least one person on
> reddit thought it's a major loss of a guarantee.
> 
what he would think of Lisp then :-)

>> 2. Writing - On the function definition side, I don't see much
>> difference in *writing* "lazy int dg" or "int delegate () dg". The
>> functions that take lazy parameter are not written daily - their
>> usage is much more frequent (enforce, logging).
>> 
> Nononono. There's a huge difference. If you have "lazy int x", then
> that's perceived as an int with some sort of storage class. Then a
> putative user would expect
> 
> auto y = x;
> 
> to define another int. In fact it's unclear whether y should be an int
> or a delegate. The presence of the delegate type clarifies what's
> going on. I could come up with several other examples that reveal
> "lazy int x" to be a complete crock.
> 
You are right, I didn't noticed that. I always perceived "()" in "foo()" as forcing of computation. Properties or real lazy evaluation could solved this maybe, but ...

Yank it. 

Although the possibility to specify if delegate accept expression or just function pointer really should be retained. How about:

void fun (@expr int delegate () dg) {...}

instead of lazy. While normal delegate parameters will work as they are now.

>> One problem I see currently with "lazy" that by specification it can
>> be evaluated zero or more times. For me, "lazy" means zero or one
>> time (compiler should handle this internally). This is not
>> particularly important, because it is probably not so hard for
>> programmer to write correct function - evaluation as many times as
>> needed (which I think is usually 0 or 1 anyway). Just, the name
>> "lazy" does not seems correct to me.
>> 
> I agree. That's why I say we yank it and at most allow function and
> delegate parameters to accept expressions. That approach has its own
> problems. Consider:
> 
> void fun(int delegate() dg) { ... }
> int delegate() gun() { ... }
> fun(gun());
> 
> In this case gun does get evaluated :o).

@expr above does not have this prob.

> 
> Andrei
> 

I think @expr delegate is it.

Another possible ussage could be:
@expr int delegate () x = 1 + 1;
@expr auto y = 1 + 1;  // y has type "int delegate ()"


1 2 3
Next ›   Last »