Jump to page: 1 28  
Page
Thread overview
Lazy eval
Aug 21, 2006
Frank Benoit
Aug 21, 2006
Frank Benoit
Aug 21, 2006
Pragma
Aug 21, 2006
Walter Bright
Aug 21, 2006
Frank Benoit
Aug 21, 2006
kris
Aug 21, 2006
Tom S
Aug 21, 2006
Sean Kelly
Aug 21, 2006
kris
Aug 21, 2006
Frank Benoit
Aug 21, 2006
Derek Parnell
Aug 21, 2006
kris
Aug 21, 2006
nobody
Aug 22, 2006
Derek Parnell
Aug 21, 2006
Lutger
Aug 22, 2006
Oskar Linde
Aug 21, 2006
Tom S
Aug 21, 2006
Frank Benoit
Aug 21, 2006
Tom S
Aug 21, 2006
Frank Benoit
Aug 21, 2006
Walter Bright
Aug 21, 2006
kris
Aug 21, 2006
Frank Benoit
Aug 22, 2006
Derek Parnell
Aug 22, 2006
Walter Bright
Aug 22, 2006
Derek Parnell
Aug 22, 2006
Walter Bright
Aug 22, 2006
Derek Parnell
Aug 22, 2006
Walter Bright
Aug 22, 2006
Sean Kelly
Aug 22, 2006
BCS
Aug 22, 2006
Walter Bright
Aug 22, 2006
John Reimer
Aug 22, 2006
kris
Aug 22, 2006
Walter Bright
Prefer { } syntax? - was Re: Lazy eval
Aug 22, 2006
Chris Miller
Aug 22, 2006
Walter Bright
about { expr }syntax for anonymous delegate
Aug 22, 2006
Sai
Aug 22, 2006
kris
Re: Lazy eval -- an example issue
Aug 21, 2006
kris
Aug 22, 2006
Walter Bright
Aug 22, 2006
kris
Aug 22, 2006
Walter Bright
Aug 22, 2006
kris
Aug 22, 2006
kris
Aug 22, 2006
Walter Bright
Aug 22, 2006
Sean Kelly
Aug 22, 2006
Walter Bright
Aug 23, 2006
Sean Kelly
Aug 23, 2006
kris
Iterators (Was: Re: Lazy eval -- an example issue)
Aug 25, 2006
Oskar Linde
Aug 31, 2006
Sean Kelly
Aug 22, 2006
kris
Aug 22, 2006
Oskar Linde
Aug 23, 2006
Walter Bright
Aug 23, 2006
kris
Aug 23, 2006
Paolo Invernizzi
Aug 23, 2006
John Reimer
Aug 23, 2006
kris
Aug 24, 2006
Paolo Invernizzi
Aug 24, 2006
kris
Aug 23, 2006
kris
Aug 22, 2006
Sean Kelly
Aug 23, 2006
Walter Bright
Aug 23, 2006
BCS
Aug 22, 2006
BCS
Aug 22, 2006
Frank Benoit
Aug 23, 2006
Walter Bright
Aug 23, 2006
Stewart Gordon
Aug 23, 2006
Frank Benoit
Aug 23, 2006
Stewart Gordon
Aug 25, 2006
Stewart Gordon
August 21, 2006
I think the lazy eval is a great feature, but in this form it has also great drawbacks.

The code isn't that much readable as it was before. You don't know what will happen. Will that expression be evaluated or not? Or will it be evaluated more than once?

There is no possibility to choose between

func( char[] a ) vs. func( char[] delegate() dg )

func( funcRetInt() ); vs. func( &funcRetInt );

It would be really important for me to have readable code. I want to look at the code, and want to have an impression what will happen.

What really would help, is if the the delegate is marked in some way as such. In the last releases of DMD the {} syntax was there. With it you needed the return statement. Perhaps we can choose the {} syntax with an optional return statement....


{ "abc"         } => char[] delegate()
{ return "abc"; } => char[] delegate()

func( "abc" ) calls func( char[] a )
func({ "abc" }) calls func( char[] delegate() dg )
func({ return "abc"; }) calls func( char[] delegate() dg )

With that syntax one can immidiatly see "this is a delegate, if it is called or not or more than once depends on func()" and the more typing of {} is not too much.

Frank

August 21, 2006
One more argument against the lazy-eval in the current form:

If you have no chance to figure out what the code does, without looking
at docs or function signature....
you will end up in writing 3 times more lines. Making each statements
separated, to be sure to get them evaluated exactly once, without
looking all that stuff up.

August 21, 2006
Frank Benoit wrote:
> I think the lazy eval is a great feature, but in this form it has also
> great drawbacks.
> 
> The code isn't that much readable as it was before. You don't know what
> will happen. Will that expression be evaluated or not? Or will it be
> evaluated more than once?

It's true there is no clue from the user's side which it is. But there also isn't a clue whether the arguments are in, out, or inout. There also is no syntactic clue what the function *does*. One must look at the function interface and documentation to use it successfully anyway.

It's going to take some caution to use this capability in a productive way.


> There is no possibility to choose between
> 
> func( char[] a ) vs. func( char[] delegate() dg )
> 
> func( funcRetInt() ); vs. func( &funcRetInt );

That's right.

> It would be really important for me to have readable code. I want to
> look at the code, and want to have an impression what will happen.

I hear you, but I'll argue that the onus is on the function designer to have a name for the function that clues the user in to what it does. I know my example code has functions named "foo" a lot, but such a generic meaningless name would be unacceptable for production code.


> What really would help, is if the the delegate is marked in some way as
> such. In the last releases of DMD the {} syntax was there. With it you
> needed the return statement. Perhaps we can choose the {} syntax with an
> optional return statement....
> 
> 
> { "abc"         } => char[] delegate()
> { return "abc"; } => char[] delegate()
> 
> func( "abc" ) calls func( char[] a )
> func({ "abc" }) calls func( char[] delegate() dg )
> func({ return "abc"; }) calls func( char[] delegate() dg )
> 
> With that syntax one can immidiatly see "this is a delegate, if it is
> called or not or more than once depends on func()" and the more typing
> of {} is not too much.

I agree with you that replacing exp with { return exp; } is clear and not much additional typing. But I've discovered over and over to my surprise that the additional typing causes people to not realize that D has that capability. The extra typing simply kills it.
August 21, 2006
Frank Benoit wrote:
> One more argument against the lazy-eval in the current form:
> 
> If you have no chance to figure out what the code does, without looking
> at docs or function signature....
> you will end up in writing 3 times more lines. Making each statements
> separated, to be sure to get them evaluated exactly once, without
> looking all that stuff up.
> 

You're right that the lazy eval, in it's fullest form, is a very stealthy (and arguably confusing) modification to the language.  I have some similar concerns myself.

However, Walter makes use of a slightly more obvious idiom in his discussion of this feature:

void log(char[] delegate() dg)
{
    if (logging)
	fwritefln(logfile, dg());
}

void foo(int i)
{
    log( { return "Entering foo() with i set to " ~ toString(i); });
}

IMO, this is probably the best way to go as it is perfectly obvious what is going on.  I like to think of it's counterpart (completely implicit conversion of expressions to delegates) as something a little more apt for generic programming - like being able to swap out a delegate for something else entirely.

-- 
- EricAnderton at yahoo
August 21, 2006
> I agree with you that replacing exp with { return exp; } is clear and not much additional typing. But I've discovered over and over to my surprise that the additional typing causes people to not realize that D has that capability. The extra typing simply kills it.

I use the { return ...; } very much. And I like it very much. And I fully agree that the return..; is annoying, because if often use it for a search criteria or something like that. The syntax { singlestatement } would be pretty cool. But leaving the braces completely out it terrible. And {} is really not too much to type.

Imagine the terrible bugs that will occur with that. I think one of the biggest advantages of D vs. C++ is the readability. That is so important. Really. Please don't destroy that.
August 21, 2006
While I partly agree with you, Frank, I don't want to dismiss this new feature too soon. So let me disagree a bit ;)


Frank Benoit wrote:
> There is no possibility to choose between
>
> func( char[] a ) vs. func( char[] delegate() dg )
>
> func( funcRetInt() ); vs. func( &funcRetInt );


That is a serious problem as it breaks existing code. But if these functions were written with lazy evaluation in mind, there would be no sense in having such two overloads. The coder would ensure that the expression is evaluated just once.
In order to overcome the problem with code having both func(Type) and func(Type delegate()) overloads, but not really meaning them to be used with lazy expression evaluation, the coder would have to make it straight that lazy evaluation is preferred in the remaining cases.

One possible method to accomplish it is by adding a new storage specifier, 'lazy' to the bunch of 'in', 'inout' and 'out'.

The consequences of such an approach would be:


----
void foo(lazy int x) {
	static assert(is(typeof(x) : int delegate()));
	writefln(x());
}

void foo(int x) {
	writefln(x);
}
---
Error: foo(lazy int) conflicts with foo(int)



----
void foo(lazy int x) {
	static assert(is(typeof(x) : int delegate()));
	writefln(x());
}

void bar(int delegate() x) {
	foo(x);
}

void bar(int x) {
	writefln(x);
}


foo({return 5;});	// foo(lazy int) called
foo(5 + 5);			// foo(lazy int) called, expression evaluated lazily
bar(5);				// bar(int) called
foo(5 + 5);			// bar(int) called, expression evaluated at call-time
bar({return 5;});	// bar(int delegate()) called
----


Which really means that lazy args and delegates could be converted between each other without explicit casts, but in order to make a function accept lazily-evaluated expressions, the programmer would have to declare his/her intent clearly.



> The code isn't that much readable as it was before. You don't know what
> will happen. Will that expression be evaluated or not? Or will it be
> evaluated more than once?

Just as Walter stated, that's the same case as with 'in' vs 'inout' vs 'out' arguments. You don't know what will happen in either case


--
Tomasz Stachowiak
August 21, 2006
Frank Benoit wrote:
>>I agree with you that replacing exp with { return exp; } is clear and
>>not much additional typing. But I've discovered over and over to my
>>surprise that the additional typing causes people to not realize that D
>>has that capability. The extra typing simply kills it.
> 
> 
> I use the { return ...; } very much. And I like it very much. And I
> fully agree that the return..; is annoying, because if often use it for
> a search criteria or something like that. The syntax { singlestatement }
> would be pretty cool. But leaving the braces completely out it terrible.
> And {} is really not too much to type.
> 
> Imagine the terrible bugs that will occur with that. I think one of the
> biggest advantages of D vs. C++ is the readability. That is so
> important. Really. Please don't destroy that.


I think the new sugar works really well where the code in question is *designed* around the notion of callbacks. The cues are already solidly in place at that point, so it may be less of an issue there? I'm thinking specifically of the logging examples, and some fairly advanced distributed processing paradigms.

However, in typical or 'mixed' D programming, the lack of cues in this latest sugar will surely become problematic. Walter suggests the author of the callee should use an appropriate name, such that overloading would (presumeably) not be an issue and the appropriate cues would be retained. One has to wonder if that is a good idea or not.

If it were possible to make the '{' '}' optional, for example, then another option would be for the coder to "make the call" as to how readable/explicit the code actually is. This is typical the case anyway, since any coder can write obfuscated code regardless of the language :)

The question is then "how much different is it to add or omit the 'return' keyword?" ... personally, I think it makes a big difference; so does Walter, apparently. Thus, if we had a choice of writing these three options:


# int i;
# somefunk (++i);
#
# or
#
# somefunk ({++i});
#
# or
#
# somefunk (return {++i;});

I think the later should be dropped, and the former two supported :)







August 21, 2006
kris wrote:
> Frank Benoit wrote:
>>> I agree with you that replacing exp with { return exp; } is clear and
>>> not much additional typing. But I've discovered over and over to my
>>> surprise that the additional typing causes people to not realize that D
>>> has that capability. The extra typing simply kills it.
>>
>>
>> I use the { return ...; } very much. And I like it very much. And I
>> fully agree that the return..; is annoying, because if often use it for
>> a search criteria or something like that. The syntax { singlestatement }
>> would be pretty cool. But leaving the braces completely out it terrible.
>> And {} is really not too much to type.
>>
>> Imagine the terrible bugs that will occur with that. I think one of the
>> biggest advantages of D vs. C++ is the readability. That is so
>> important. Really. Please don't destroy that.
> 
> 
> I think the new sugar works really well where the code in question is *designed* around the notion of callbacks. The cues are already solidly in place at that point, so it may be less of an issue there? I'm thinking specifically of the logging examples, and some fairly advanced distributed processing paradigms.
> 
> However, in typical or 'mixed' D programming, the lack of cues in this latest sugar will surely become problematic. Walter suggests the author of the callee should use an appropriate name, such that overloading would (presumeably) not be an issue and the appropriate cues would be retained. One has to wonder if that is a good idea or not.
> 
> If it were possible to make the '{' '}' optional, for example, then another option would be for the coder to "make the call" as to how readable/explicit the code actually is. This is typical the case anyway, since any coder can write obfuscated code regardless of the language :)
> 
> The question is then "how much different is it to add or omit the 'return' keyword?" ... personally, I think it makes a big difference; so does Walter, apparently. Thus, if we had a choice of writing these three options:
> 
> 
> # int i;
> # somefunk (++i);
> #
> # or
> #
> # somefunk ({++i});
> #
> # or
> #
> # somefunk (return {++i;});
> 
> I think the later should be dropped, and the former two supported :)

You have a typo in the 3rd sample, it should read:
# somefunk ({return ++i;});

... which clearly shows that the 3rd option isn't the preferred one ;)

--
Tomasz Stachowiak
August 21, 2006
On Mon, 21 Aug 2006 14:18:04 -0700, Walter Bright wrote:

> Frank Benoit wrote:
>> I think the lazy eval is a great feature, but in this form it has also great drawbacks.
>> 
>> The code isn't that much readable as it was before. You don't know what will happen. Will that expression be evaluated or not? Or will it be evaluated more than once?
> 
> It's true there is no clue from the user's side which it is. But there also isn't a clue whether the arguments are in, out, or inout. There also is no syntactic clue what the function *does*. One must look at the function interface and documentation to use it successfully anyway.
> 
> It's going to take some caution to use this capability in a productive way.
> 
>> There is no possibility to choose between
>> 
>> func( char[] a ) vs. func( char[] delegate() dg )

Would it possible to use ...

   func ( cast(char[]) "abc" );

to force the compiler to chose 'func( char[] a)' instead of the delgated
version?


-- 
Derek Parnell
Melbourne, Australia
"Down with mediocrity!"
August 21, 2006
Tom S wrote:
> kris wrote:
>> Frank Benoit wrote:
>>>> I agree with you that replacing exp with { return exp; } is clear and
>>>> not much additional typing. But I've discovered over and over to my
>>>> surprise that the additional typing causes people to not realize that D
>>>> has that capability. The extra typing simply kills it.
>>>
>>>
>>> I use the { return ...; } very much. And I like it very much. And I
>>> fully agree that the return..; is annoying, because if often use it for
>>> a search criteria or something like that. The syntax { singlestatement }
>>> would be pretty cool. But leaving the braces completely out it terrible.
>>> And {} is really not too much to type.
>>>
>>> Imagine the terrible bugs that will occur with that. I think one of the
>>> biggest advantages of D vs. C++ is the readability. That is so
>>> important. Really. Please don't destroy that.
>>
>>
>> I think the new sugar works really well where the code in question is *designed* around the notion of callbacks. The cues are already solidly in place at that point, so it may be less of an issue there? I'm thinking specifically of the logging examples, and some fairly advanced distributed processing paradigms.
>>
>> However, in typical or 'mixed' D programming, the lack of cues in this latest sugar will surely become problematic. Walter suggests the author of the callee should use an appropriate name, such that overloading would (presumeably) not be an issue and the appropriate cues would be retained. One has to wonder if that is a good idea or not.
>>
>> If it were possible to make the '{' '}' optional, for example, then another option would be for the coder to "make the call" as to how readable/explicit the code actually is. This is typical the case anyway, since any coder can write obfuscated code regardless of the language :)
>>
>> The question is then "how much different is it to add or omit the 'return' keyword?" ... personally, I think it makes a big difference; so does Walter, apparently. Thus, if we had a choice of writing these three options:
>>
>>
>> # int i;
>> # somefunk (++i);
>> #
>> # or
>> #
>> # somefunk ({++i});
>> #
>> # or
>> #
>> # somefunk (return {++i;});
>>
>> I think the later should be dropped, and the former two supported :)
> 
> You have a typo in the 3rd sample, it should read:
> # somefunk ({return ++i;});
> 
> ... which clearly shows that the 3rd option isn't the preferred one ;)

I'm not sure I'd want to do away with option 3 unless option 2 supported multiple statements and a void return in a way that made sense.


Sean
« First   ‹ Prev
1 2 3 4 5 6 7 8