www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - DMD 0.166 release

reply Walter Bright <newshound digitalmars.com> writes:
The implicit conversion to delegate just broke too much. Instead, I'm 
trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.

http://www.digitalmars.com/d/changelog.html
Aug 31 2006
next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter Bright wrote:
 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.
 
 http://www.digitalmars.com/d/changelog.html

Is there any reason to not use "lazy" as a keyword to modify the expression, rather than the parameter? void foo(int delegate() dg) {...} void bar(int x,int y) { foo(lazy x+y); }
Aug 31 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Russ Lewis wrote:
 Walter Bright wrote:
 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.

 http://www.digitalmars.com/d/changelog.html

Is there any reason to not use "lazy" as a keyword to modify the expression, rather than the parameter? void foo(int delegate() dg) {...} void bar(int x,int y) { foo(lazy x+y); }

One reason is lazy arguments and non-lazy arguments cannot be passed to the same function.
Aug 31 2006
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter Bright wrote:
 Russ Lewis wrote:
 Is there any reason to not use "lazy" as a keyword to modify the
 expression, rather than the parameter?

   void foo(int delegate() dg) {...}
   void bar(int x,int y) {
     foo(lazy x+y);
   }

One reason is lazy arguments and non-lazy arguments cannot be passed to the same function.

One of us is missing something. I'm not sure who :) Can you expand on your response here?
Aug 31 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Russ Lewis wrote:
 Walter Bright wrote:
 Russ Lewis wrote:
 Is there any reason to not use "lazy" as a keyword to modify the
 expression, rather than the parameter?

   void foo(int delegate() dg) {...}
   void bar(int x,int y) {
     foo(lazy x+y);
   }

One reason is lazy arguments and non-lazy arguments cannot be passed to the same function.

One of us is missing something. I'm not sure who :) Can you expand on your response here?

foo(x + y); foo(lazy x + y); can't work, because foo needs to know which it is. Just like you can't have the same parameter be both in and out.
Aug 31 2006
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter Bright wrote:
 Russ Lewis wrote:
 
 Walter Bright wrote:

 Russ Lewis wrote:

 Is there any reason to not use "lazy" as a keyword to modify the
 expression, rather than the parameter?

   void foo(int delegate() dg) {...}
   void bar(int x,int y) {
     foo(lazy x+y);
   }

One reason is lazy arguments and non-lazy arguments cannot be passed to the same function.

One of us is missing something. I'm not sure who :) Can you expand on your response here?

foo(x + y); foo(lazy x + y); can't work, because foo needs to know which it is. Just like you can't have the same parameter be both in and out.

Ah, I was wondering if that was what you meant. What I was suggesting was that the code lazy x+y would just be syntax sugar for delegate int() { return x+y; } So, to expand on the previous example: void foo(int delegate() dg) {...} void foo(int i) {...} void bar(int x,int y) { foo(lazy x+y); // calls delegate version foo(x+y); // calls int version }
Aug 31 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Russ Lewis wrote:
 Ah, I was wondering if that was what you meant.  What I was suggesting 
 was that the code
     lazy x+y
 would just be syntax sugar for
     delegate int() { return x+y; }
 
 So, to expand on the previous example:
   void foo(int delegate() dg) {...}
   void foo(int i) {...}
   void bar(int x,int y) {
     foo(lazy x+y); // calls delegate version
     foo(x+y);      // calls int version
   }

Ok, that can work. But I don't see an application for it.
Aug 31 2006
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter Bright wrote:
 Russ Lewis wrote:
 
 Ah, I was wondering if that was what you meant.  What I was suggesting 
 was that the code
     lazy x+y
 would just be syntax sugar for
     delegate int() { return x+y; }

 So, to expand on the previous example:
   void foo(int delegate() dg) {...}
   void foo(int i) {...}
   void bar(int x,int y) {
     foo(lazy x+y); // calls delegate version
     foo(x+y);      // calls int version
   }

Ok, that can work. But I don't see an application for it.

Heh, sems like I'm having a lot of trouble explaining myself here. I'm not trying to argue that overloading a function with both delegate and literal versions has a lot of value. I was just trying to say that the syntax I was proposing was not ambiguous. My argument is that it would be good to make laziness explicit in the caller, so that the caller of the code knows what he can expect.
Sep 01 2006
parent reply Sean Kelly <sean f4.ca> writes:
Russ Lewis wrote:
 Walter Bright wrote:
 Russ Lewis wrote:

 Ah, I was wondering if that was what you meant.  What I was 
 suggesting was that the code
     lazy x+y
 would just be syntax sugar for
     delegate int() { return x+y; }

 So, to expand on the previous example:
   void foo(int delegate() dg) {...}
   void foo(int i) {...}
   void bar(int x,int y) {
     foo(lazy x+y); // calls delegate version
     foo(x+y);      // calls int version
   }

Ok, that can work. But I don't see an application for it.

Heh, sems like I'm having a lot of trouble explaining myself here. I'm not trying to argue that overloading a function with both delegate and literal versions has a lot of value. I was just trying to say that the syntax I was proposing was not ambiguous. My argument is that it would be good to make laziness explicit in the caller, so that the caller of the code knows what he can expect.

I believe this is the same as Derek's suggestion that in/out/inout be specified at the call side as well. Sean
Sep 01 2006
next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Sean Kelly wrote:
 Russ Lewis wrote:
 Walter Bright wrote:
 Russ Lewis wrote:

 Ah, I was wondering if that was what you meant.  What I was 
 suggesting was that the code
     lazy x+y
 would just be syntax sugar for
     delegate int() { return x+y; }

 So, to expand on the previous example:
   void foo(int delegate() dg) {...}
   void foo(int i) {...}
   void bar(int x,int y) {
     foo(lazy x+y); // calls delegate version
     foo(x+y);      // calls int version
   }

Ok, that can work. But I don't see an application for it.

Heh, sems like I'm having a lot of trouble explaining myself here. I'm not trying to argue that overloading a function with both delegate and literal versions has a lot of value. I was just trying to say that the syntax I was proposing was not ambiguous.


Ok.
 My argument is that it would be good to make laziness explicit in the 
 caller, so that the caller of the code knows what he can expect.

I believe this is the same as Derek's suggestion that in/out/inout be specified at the call side as well.

Yes, it would be the same. But I think the interface should be set by the definition, not the use. That's the usual practice with programming languages, and I've never seen it raised as an issue before.
Sep 01 2006
parent reply Derek Parnell <derek psyc.ward> writes:
On Fri, 01 Sep 2006 10:59:18 -0700, Walter Bright wrote:

 suggestion that in/out/inout be 
 specified at the call side as well.

Yes, it would be the same. But I think the interface should be set by the definition, not the use.

Yes we agree. But the purpose of this suggestion is not to 'set the definition' but to 'document the usage' of the definition. The purpose is to help both the compiler and human reader to validate the intention of the coder. The definition would still be set when declaring the function but if the compiler optionally allowed parameter storage class keywords at the point of invocation, you could help ensure that the coder is doing what she intended to do. It is a form of DbC.
 That's the usual practice with programming 
 languages, and I've never seen it raised as an issue before.

So what? You are in the wonderful position of creating a useful and superb tool that can be very special. You have been a trail blazer and can continue to be one. -- Derek Parnell Melbourne, Australia "Down with mediocrity!"
Sep 01 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Derek Parnell wrote:
 On Fri, 01 Sep 2006 10:59:18 -0700, Walter Bright wrote:
 
 suggestion that in/out/inout be 
 specified at the call side as well.

the definition, not the use.

Yes we agree. But the purpose of this suggestion is not to 'set the definition' but to 'document the usage' of the definition. The purpose is to help both the compiler and human reader to validate the intention of the coder. The definition would still be set when declaring the function but if the compiler optionally allowed parameter storage class keywords at the point of invocation, you could help ensure that the coder is doing what she intended to do. It is a form of DbC.

Setting the behavior at both the point of definition and point of use may result in fewer programming bugs, it does so at the risk of making modifications harder and annoying programmers.
 That's the usual practice with programming 
 languages, and I've never seen it raised as an issue before.

So what? You are in the wonderful position of creating a useful and superb tool that can be very special. You have been a trail blazer and can continue to be one.

If people don't like adding { } around the lazy expressions, they aren't going to like putting 'lazy' in front of them, either. Every time I've seen a feature like this, the complexity was at the definition point, *not* the use point.
Sep 02 2006
next sibling parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Walter Bright wrote:
 Derek Parnell wrote:
 On Fri, 01 Sep 2006 10:59:18 -0700, Walter Bright wrote:

 suggestion that in/out/inout be specified at the call side as well.

the definition, not the use.

Yes we agree. But the purpose of this suggestion is not to 'set the definition' but to 'document the usage' of the definition. The purpose is to help both the compiler and human reader to validate the intention of the coder. The definition would still be set when declaring the function but if the compiler optionally allowed parameter storage class keywords at the point of invocation, you could help ensure that the coder is doing what she intended to do. It is a form of DbC.

Setting the behavior at both the point of definition and point of use may result in fewer programming bugs, it does so at the risk of making modifications harder and annoying programmers.
 That's the usual practice with programming languages, and I've never 
 seen it raised as an issue before.

So what? You are in the wonderful position of creating a useful and superb tool that can be very special. You have been a trail blazer and can continue to be one.

If people don't like adding { } around the lazy expressions, they aren't going to like putting 'lazy' in front of them, either. Every time I've seen a feature like this, the complexity was at the definition point, *not* the use point.

Only it isn't "{ expression }" it is: "{ expression }()".
Sep 02 2006
prev sibling parent reply Derek Parnell <derek psyc.ward> writes:
On Sat, 02 Sep 2006 12:22:45 -0700, Walter Bright wrote:

 Derek Parnell wrote:
 On Fri, 01 Sep 2006 10:59:18 -0700, Walter Bright wrote:
 
 suggestion that in/out/inout be 
 specified at the call side as well.

the definition, not the use.

Yes we agree. But the purpose of this suggestion is not to 'set the definition' but to 'document the usage' of the definition. The purpose is to help both the compiler and human reader to validate the intention of the coder. The definition would still be set when declaring the function but if the compiler optionally allowed parameter storage class keywords at the point of invocation, you could help ensure that the coder is doing what she intended to do. It is a form of DbC.

Setting the behavior at both the point of definition and point of use may result in fewer programming bugs, it does so at the risk of making modifications harder and annoying programmers.

Why is it so hard to make my thoughts known to you? I did *not* talk about "Setting the behavior at both the points". *THE* behavior is set at the declaration just as it is now. A new *AND OPTIONAL* behavior can be set at point of use. This new behavior of the compiler would be such that if no parameter storage class is used for a parameter then the compiler does nothing new (the default case). If the coder chooses to include an 'in', 'inout', 'out' or 'lazy' at the point of use then the compiler could ensure that the coder's belief in how the declararion signature is can be tested by the compiler and alert the coder to any mismatch. This *will* result in fewer bugs at the 'cost' of making the code easier to understand when read by a human. How is it annoying? If the coder chooses to use this feature then obviously they are not annoyed by it. If a future coder does not like this DbC feature then they can remove it, just as they can remove all those annoying "in{} out{} body{}" phrases.
 That's the usual practice with programming 
 languages, and I've never seen it raised as an issue before.

So what? You are in the wonderful position of creating a useful and superb tool that can be very special. You have been a trail blazer and can continue to be one.

If people don't like adding { } around the lazy expressions, they aren't going to like putting 'lazy' in front of them, either. Every time I've seen a feature like this, the complexity was at the definition point, *not* the use point.

You seem to be think that this would be a mandatory requirement of the language where as I'm consistantly talking about optional, coder chosen, stuff. For example, I willing choose to use syntax that is 'wordier' in order to increase the ability of other humans to understand what I was intending by my coding. If you or anyone else choose not to do that, then fine. -- Derek Parnell Melbourne, Australia "Down with mediocrity!"
Sep 02 2006
next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Derek Parnell wrote:
 On Sat, 02 Sep 2006 12:22:45 -0700, Walter Bright wrote:
 
 
Derek Parnell wrote:

On Fri, 01 Sep 2006 10:59:18 -0700, Walter Bright wrote:


suggestion that in/out/inout be 
specified at the call side as well.

Yes, it would be the same. But I think the interface should be set by the definition, not the use.

Yes we agree. But the purpose of this suggestion is not to 'set the definition' but to 'document the usage' of the definition. The purpose is to help both the compiler and human reader to validate the intention of the coder. The definition would still be set when declaring the function but if the compiler optionally allowed parameter storage class keywords at the point of invocation, you could help ensure that the coder is doing what she intended to do. It is a form of DbC.

Setting the behavior at both the point of definition and point of use may result in fewer programming bugs, it does so at the risk of making modifications harder and annoying programmers.

Why is it so hard to make my thoughts known to you? I did *not* talk about "Setting the behavior at both the points". *THE* behavior is set at the declaration just as it is now. A new *AND OPTIONAL* behavior can be set at point of use. This new behavior of the compiler would be such that if no parameter storage class is used for a parameter then the compiler does nothing new (the default case). If the coder chooses to include an 'in', 'inout', 'out' or 'lazy' at the point of use then the compiler could ensure that the coder's belief in how the declararion signature is can be tested by the compiler and alert the coder to any mismatch. This *will* result in fewer bugs at the 'cost' of making the code easier to understand when read by a human. How is it annoying? If the coder chooses to use this feature then obviously they are not annoyed by it. If a future coder does not like this DbC feature then they can remove it, just as they can remove all those annoying "in{} out{} body{}" phrases.
That's the usual practice with programming 
languages, and I've never seen it raised as an issue before.

So what? You are in the wonderful position of creating a useful and superb tool that can be very special. You have been a trail blazer and can continue to be one.

If people don't like adding { } around the lazy expressions, they aren't going to like putting 'lazy' in front of them, either. Every time I've seen a feature like this, the complexity was at the definition point, *not* the use point.

You seem to be think that this would be a mandatory requirement of the language where as I'm consistantly talking about optional, coder chosen, stuff. For example, I willing choose to use syntax that is 'wordier' in order to increase the ability of other humans to understand what I was intending by my coding. If you or anyone else choose not to do that, then fine.

I admit that I must have misunderstood as well, but looking at it this way I actually feel supportive. This actually strikes me as similar to our already-optional 'override' attribute, which asks the compiler to ensure that our method actually does override a parent method. And if it does not, the compiler issues a helpful error. "Yay! Now we have an alert for API changes!" I see the ability to *optionally* apply in/out/inout/lazy redundantly at the caller as living in the same usefulness category. It would alert to API changes, and would make it clear that the call expression is reliant on the callee exhibiting certain behavior. I think I would probably use this, albeit sparingly. -- Chris Nicholson-Sauls
Sep 02 2006
prev sibling next sibling parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Derek Parnell wrote:
 Why is it so hard to make my thoughts known to you? 
 
 I did *not* talk about "Setting the behavior at both the points". *THE*
 behavior is set at the declaration just as it is now. A new *AND OPTIONAL*
 behavior can be set at point of use. This new behavior of the compiler
 would be such that if no parameter storage class is used for a parameter
 then the compiler does nothing new (the default case). If the coder chooses
 to include an 'in', 'inout', 'out' or 'lazy' at the point of use then the
 compiler could ensure that the coder's belief in how the declararion
 signature is can be tested by the compiler and alert the coder to any
 mismatch. 

This is a feature I would certainly be using. It can't do any harm but can have extremely positive effects.
Sep 03 2006
parent "Rioshin an'Harthen" <rharth75 hotmail.com> writes:
"Ivan Senji" <ivan.senji_REMOVE_ _THIS__gmail.com> wrote:
 Derek Parnell wrote:
 Why is it so hard to make my thoughts known to you? I did *not* talk 
 about "Setting the behavior at both the points". *THE*
 behavior is set at the declaration just as it is now. A new *AND 
 OPTIONAL*
 behavior can be set at point of use. This new behavior of the compiler
 would be such that if no parameter storage class is used for a parameter
 then the compiler does nothing new (the default case). If the coder 
 chooses
 to include an 'in', 'inout', 'out' or 'lazy' at the point of use then the
 compiler could ensure that the coder's belief in how the declararion
 signature is can be tested by the compiler and alert the coder to any
 mismatch.

This is a feature I would certainly be using. It can't do any harm but can have extremely positive effects.

I'll chime in with a resounding "me, too". Having in, out, inout or lazy marked at the place of calling would help returning to the same code later.
Sep 03 2006
prev sibling parent Walter Bright <newshound digitalmars.com> writes:
Derek Parnell wrote:
 I did *not* talk about "Setting the behavior at both the points". *THE*
 behavior is set at the declaration just as it is now. A new *AND OPTIONAL*
 behavior can be set at point of use. This new behavior of the compiler
 would be such that if no parameter storage class is used for a parameter
 then the compiler does nothing new (the default case). If the coder chooses
 to include an 'in', 'inout', 'out' or 'lazy' at the point of use then the
 compiler could ensure that the coder's belief in how the declararion
 signature is can be tested by the compiler and alert the coder to any
 mismatch. 

I misunderstood you. I didn't catch the optional bit. Sorry.
Sep 03 2006
prev sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Sean Kelly wrote:
 Russ Lewis wrote:
 Walter Bright wrote:
 Russ Lewis wrote:

 Ah, I was wondering if that was what you meant.  What I was 
 suggesting was that the code
     lazy x+y
 would just be syntax sugar for
     delegate int() { return x+y; }

 So, to expand on the previous example:
   void foo(int delegate() dg) {...}
   void foo(int i) {...}
   void bar(int x,int y) {
     foo(lazy x+y); // calls delegate version
     foo(x+y);      // calls int version
   }

Ok, that can work. But I don't see an application for it.

Heh, sems like I'm having a lot of trouble explaining myself here. I'm not trying to argue that overloading a function with both delegate and literal versions has a lot of value. I was just trying to say that the syntax I was proposing was not ambiguous.


Ok.
 My argument is that it would be good to make laziness explicit in the 
 caller, so that the caller of the code knows what he can expect.

I believe this is the same as Derek's suggestion that in/out/inout be specified at the call side as well.

Yes, it would be the same. But I think the interface should be set by the definition, not the use. That's the usual practice with programming languages, and I've never seen it raised as an issue before.
Sep 01 2006
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter Bright wrote:
 Yes, it would be the same. But I think the interface should be set by 
 the definition, not the use. That's the usual practice with programming 
 languages, and I've never seen it raised as an issue before.

By that logic, shouldn't I be able to pass a delegate to a function with pass-by-value semantics and have the delegate get automagically called and converted into a value? Assuming that you'll answer "no," they why is it ok for it to work the other way around?
Sep 05 2006
prev sibling next sibling parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Walter Bright wrote:
 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.
 
 http://www.digitalmars.com/d/changelog.html

Thanks Walter :) And thank you Oskar ! Now we can play with more IFTI :)
Aug 31 2006
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Walter Bright" <newshound digitalmars.com> wrote in message 
news:ed79pv$3fc$1 digitaldaemon.com...
 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.

 http://www.digitalmars.com/d/changelog.html

Ahh, thank you. I wasn't really keen on the lazy stuff. I'd probably never use it, but the new syntax is a lot nicer (and more explicit).
Aug 31 2006
prev sibling next sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Walter Bright wrote:
 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.
 
 http://www.digitalmars.com/d/changelog.html

Nice. I'll have to play with the improved IFTI support. Also, I've added "lazy" to the keyword index: http://www.prowiki.org/wiki4d/wiki.cgi?LanguageSpecification/KeywordIndex -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Aug 31 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message 
news:ed7ddg$6r2$1 digitaldaemon.com...

 Nice. I'll have to play with the improved IFTI support.

Hm. I missed this new feature. What does it include? There's not even a link to a conversation, and I don't remember any threads about this.
Aug 31 2006
next sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Jarrett Billingsley wrote:
 "Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message 
 news:ed7ddg$6r2$1 digitaldaemon.com...
 
 
Nice. I'll have to play with the improved IFTI support.

Hm. I missed this new feature. What does it include? There's not even a link to a conversation, and I don't remember any threads about this.

I'm referring to Oskar Linde's member template patches. -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Aug 31 2006
prev sibling next sibling parent reply Oskar Linde <olREM OVEnada.kth.se> writes:
Jarrett Billingsley wrote:

 "Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message
 news:ed7ddg$6r2$1 digitaldaemon.com...
 
 Nice. I'll have to play with the improved IFTI support.

Hm. I missed this new feature. What does it include? There's not even a link to a conversation, and I don't remember any threads about this.

It is really just a small patch that enables implicit function template instantiation for member function and operator templates. It should work identically to how IFTI works for free functions. It should open up quite a few door. Here is a quick demo I hacked together of how compile time dimensionality checking can be implemented: http://www.csc.kth.se/~ol/physical.d /Oskar
Aug 31 2006
next sibling parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Oskar Linde wrote:
 Jarrett Billingsley wrote:
 
 "Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message
 news:ed7ddg$6r2$1 digitaldaemon.com...

 Nice. I'll have to play with the improved IFTI support.

link to a conversation, and I don't remember any threads about this.

It is really just a small patch that enables implicit function template instantiation for member function and operator templates. It should work identically to how IFTI works for free functions. It should open up quite a few door. Here is a quick demo I hacked together of how compile time dimensionality checking can be implemented: http://www.csc.kth.se/~ol/physical.d

Very, very nice!
 
 /Oskar
 
 

Aug 31 2006
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Oskar Linde" <olREM OVEnada.kth.se> wrote in message 
news:ed7i39$bke$1 digitaldaemon.com...

 It is really just a small patch that enables implicit function template
 instantiation for member function and operator templates. It should work
 identically to how IFTI works for free functions.

Ah!! This exactly solves the problem I was (am!) having with needing several very similar member methods which only differ by the parameter type. Thanks!
 It should open up quite a few door. Here is a quick demo I hacked together
 of how compile time dimensionality checking can be implemented:

 http://www.csc.kth.se/~ol/physical.d

That is really, really cool :)
Aug 31 2006
prev sibling next sibling parent reply BCS <BCS pathlink.com> writes:
Oskar Linde wrote:
 Jarrett Billingsley wrote:
 
 
"Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message
news:ed7ddg$6r2$1 digitaldaemon.com...


Nice. I'll have to play with the improved IFTI support.

Hm. I missed this new feature. What does it include? There's not even a link to a conversation, and I don't remember any threads about this.

It is really just a small patch that enables implicit function template instantiation for member function and operator templates. It should work identically to how IFTI works for free functions. It should open up quite a few door. Here is a quick demo I hacked together of how compile time dimensionality checking can be implemented: http://www.csc.kth.se/~ol/physical.d /Oskar

Hot, Dog!!! This is a project I was hoping to get to a LONG time ago. (The d code side, not the getting-D-to-do-this side) Best I came up with was a Runtime version. http://www.webpages.uidaho.edu/~shro8822/unit.d Mind if I try to graft in a "few" ;) more units and some unittest?
Aug 31 2006
parent reply Oskar Linde <olREM OVEnada.kth.se> writes:
BCS wrote:

 Oskar Linde wrote:
 Jarrett Billingsley wrote:
 
 
"Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message
news:ed7ddg$6r2$1 digitaldaemon.com...


Nice. I'll have to play with the improved IFTI support.

Hm. I missed this new feature. What does it include? There's not even a link to a conversation, and I don't remember any threads about this.

It is really just a small patch that enables implicit function template instantiation for member function and operator templates. It should work identically to how IFTI works for free functions. It should open up quite a few door. Here is a quick demo I hacked together of how compile time dimensionality checking can be implemented: http://www.csc.kth.se/~ol/physical.d /Oskar

Hot, Dog!!! This is a project I was hoping to get to a LONG time ago. (The d code side, not the getting-D-to-do-this side) Best I came up with was a Runtime version. http://www.webpages.uidaho.edu/~shro8822/unit.d Mind if I try to graft in a "few" ;) more units and some unittest?

Certainly not. Feel free to go ahead. :) But as I said, this is just a quick hack. Some improvements would be a generic Quantity supporting an arbitrary number of dimensions and rational exponents. /Oskar
Sep 02 2006
parent BCS <BCS pathlink.com> writes:
Oskar Linde wrote:
 BCS wrote:
 
Hot, Dog!!!

This is a project I was hoping to get to a LONG time ago. (The d code
side, not the getting-D-to-do-this side)

Best I came up with was a Runtime version.

http://www.webpages.uidaho.edu/~shro8822/unit.d

Mind if I try to graft in a "few" ;) more units and some unittest?

Certainly not. Feel free to go ahead. :) But as I said, this is just a quick hack. Some improvements would be a generic Quantity supporting an arbitrary number of dimensions and rational exponents. /Oskar

I think 7d is actually more than is needed (But I'm no expert). Mine only used 5d (mole is unit less and candle is power/area). Also I can't ever remember ending up with non integer powers on a dimension. As it stands, the template provides a lot of functionality. I think that the next thing to be added should be a set of function (sqrt, pow, etc). Any thought on how to get them to work without having them be wrappers?
Sep 02 2006
prev sibling parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Fri, 01 Sep 2006 00:50:48 +0200, Oskar Linde wrote:

 Jarrett Billingsley wrote:
 
 "Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message
 news:ed7ddg$6r2$1 digitaldaemon.com...
 
 Nice. I'll have to play with the improved IFTI support.

Hm. I missed this new feature. What does it include? There's not even a link to a conversation, and I don't remember any threads about this.

It is really just a small patch that enables implicit function template instantiation for member function and operator templates. It should work identically to how IFTI works for free functions. It should open up quite a few door. Here is a quick demo I hacked together of how compile time dimensionality checking can be implemented: http://www.csc.kth.se/~ol/physical.d /Oskar

In your example code you have ... // One wishes the .toString was unnecessary... writefln("A current of ",i.toString); writefln("through a voltage of ",v.toString); writefln("requires a resistance of ",r.toString); writefln("and produces ",w.toString," of heat."); writefln("Total energy used in ",ti.toString," is ",e.toString); but could you not also use ... writefln("A current of %s",i); writefln("through a voltage of %s",v); writefln("requires a resistance of %s",r); writefln("and produces %s of heat.",w); writefln("Total energy used in %s is %s",ti,e); -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 1/09/2006 12:02:44 PM
Aug 31 2006
parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Derek Parnell wrote:
 On Fri, 01 Sep 2006 00:50:48 +0200, Oskar Linde wrote:
 
 Jarrett Billingsley wrote:

 "Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message
 news:ed7ddg$6r2$1 digitaldaemon.com...

 Nice. I'll have to play with the improved IFTI support.

link to a conversation, and I don't remember any threads about this.

instantiation for member function and operator templates. It should work identically to how IFTI works for free functions. It should open up quite a few door. Here is a quick demo I hacked together of how compile time dimensionality checking can be implemented: http://www.csc.kth.se/~ol/physical.d /Oskar

In your example code you have ... // One wishes the .toString was unnecessary... writefln("A current of ",i.toString); writefln("through a voltage of ",v.toString); writefln("requires a resistance of ",r.toString); writefln("and produces ",w.toString," of heat."); writefln("Total energy used in ",ti.toString," is ",e.toString); but could you not also use ... writefln("A current of %s",i); writefln("through a voltage of %s",v); writefln("requires a resistance of %s",r); writefln("and produces %s of heat.",w); writefln("Total energy used in %s is %s",ti,e);

Nope, since it only works for classes, and his SiQuantity is a struct
Aug 31 2006
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Fri, 01 Sep 2006 04:08:28 +0100, Tom S wrote:

 Derek Parnell wrote:
 On Fri, 01 Sep 2006 00:50:48 +0200, Oskar Linde wrote:
 
 Jarrett Billingsley wrote:

 "Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message
 news:ed7ddg$6r2$1 digitaldaemon.com...

 Nice. I'll have to play with the improved IFTI support.

link to a conversation, and I don't remember any threads about this.

instantiation for member function and operator templates. It should work identically to how IFTI works for free functions. It should open up quite a few door. Here is a quick demo I hacked together of how compile time dimensionality checking can be implemented: http://www.csc.kth.se/~ol/physical.d /Oskar

In your example code you have ... // One wishes the .toString was unnecessary... writefln("A current of ",i.toString); writefln("through a voltage of ",v.toString); writefln("requires a resistance of ",r.toString); writefln("and produces ",w.toString," of heat."); writefln("Total energy used in ",ti.toString," is ",e.toString); but could you not also use ... writefln("A current of %s",i); writefln("through a voltage of %s",v); writefln("requires a resistance of %s",r); writefln("and produces %s of heat.",w); writefln("Total energy used in %s is %s",ti,e);

Nope, since it only works for classes, and his SiQuantity is a struct

Damn! I didn't know that. What's the rationale for such a seemingly arbitrary restriction? -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 1/09/2006 1:17:19 PM
Aug 31 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Derek Parnell wrote:
 Damn! I didn't know that. What's the rationale for such a seemingly
 arbitrary restriction?

No virtual functions for structs!
Aug 31 2006
next sibling parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Thu, 31 Aug 2006 20:32:01 -0700, Walter Bright wrote:

 Derek Parnell wrote:
 Damn! I didn't know that. What's the rationale for such a seemingly
 arbitrary restriction?

No virtual functions for structs!

Ok, that meant nothing to me until I translated it from the OO jargon. Here is my attempt at converting Walter's answer into human speech ;-) The 'format' function examines each parameter supplied to it in order to convert it into some form of string. When it comes to a class object, it casts the object instance to 'Object' and then calls Object.toString(), which through the magic of 'virtual functions' actually gets around to calling the parameter's own toString() method if it exists. 'virtual functions' is the mechanism in which derived classes can have their methods called via reference to their parent class. Now structs are not derived from anything and thus there cannot be a generic toString() method in a struct parent. So the 'format' function doesn't know which struct toString() to call and it throws the exception instead. I guess that when D eventually gets runtime reflection we will be able to improve 'format' to check if the struct parameter passed to it has a toString method and thus call it. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 1/09/2006 2:29:34 PM
Aug 31 2006
next sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Derek Parnell wrote:
 I guess that when D eventually gets runtime reflection we will be able to
 improve 'format' to check if the struct parameter passed to it has a
 toString method and thus call it.

It could also be done with variadic templates. -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Aug 31 2006
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Derek Parnell wrote:
 On Thu, 31 Aug 2006 20:32:01 -0700, Walter Bright wrote:
 
 Derek Parnell wrote:
 Damn! I didn't know that. What's the rationale for such a seemingly
 arbitrary restriction?


Ok, that meant nothing to me until I translated it from the OO jargon. Here is my attempt at converting Walter's answer into human speech ;-) The 'format' function examines each parameter supplied to it in order to convert it into some form of string. When it comes to a class object, it casts the object instance to 'Object' and then calls Object.toString(), which through the magic of 'virtual functions' actually gets around to calling the parameter's own toString() method if it exists. 'virtual functions' is the mechanism in which derived classes can have their methods called via reference to their parent class. Now structs are not derived from anything and thus there cannot be a generic toString() method in a struct parent. So the 'format' function doesn't know which struct toString() to call and it throws the exception instead. I guess that when D eventually gets runtime reflection we will be able to improve 'format' to check if the struct parameter passed to it has a toString method and thus call it.

Another alternative is a syntax using the concatenation operator: writefln("through a voltage of" ~ v); This can be done already with overloading of opCat_r and opCat, but it's way less than ideal since it has to be done for every new type. Or D could be changed so that '~' itself would try to call toString() if it existed. Yet another alternative is for any type that has a toString() member function to be implicitly castable to string (aka "char[]"). Then writefln would be declared as a typesafe variadic function of (string[] strs ...). It would also be necessary for implicit casting to work with typesafe variadic function calls, which seems it doesn't (I wonder if that's by design?). And it would be necessary for primitives to have toString "member functions" (it's unusual, but I don't see any problem with that. Primitives already have properties for example). Usage would be: writeln("X is ", 1.2345 ); Note we would lose the formatting capabilities(no "f"). To do formatting we could do for example: writeln("X is ", (1.2345).toString("%1.2d") ); Just some wacky ideas. :P -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 01 2006
prev sibling parent reply Oskar Linde <olREM OVEnada.kth.se> writes:
Walter Bright wrote:

 Derek Parnell wrote:
 Damn! I didn't know that. What's the rationale for such a seemingly
 arbitrary restriction?

No virtual functions for structs!

If one considered toString() important enough it could be added to the TypeInfo for structs, just like toHash, opEquals and opCmp are today. It would make certain sense to support all the methods of Object in this way. /Oskar
Sep 02 2006
parent Walter Bright <newshound digitalmars.com> writes:
Oskar Linde wrote:
 Walter Bright wrote:
 
 Derek Parnell wrote:
 Damn! I didn't know that. What's the rationale for such a seemingly
 arbitrary restriction?


If one considered toString() important enough it could be added to the TypeInfo for structs, just like toHash, opEquals and opCmp are today. It would make certain sense to support all the methods of Object in this way.

That makes sense.
Sep 02 2006
prev sibling parent Walter Bright <newshound digitalmars.com> writes:
Jarrett Billingsley wrote:
 "Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message 
 news:ed7ddg$6r2$1 digitaldaemon.com...
 
 Nice. I'll have to play with the improved IFTI support.

Hm. I missed this new feature. What does it include? There's not even a link to a conversation, and I don't remember any threads about this.

Oskar had emailed me the patches.
Aug 31 2006
prev sibling next sibling parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Walter Bright wrote:
 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.
 
 http://www.digitalmars.com/d/changelog.html

Hmm, I am afraid I have to admit I'm a little bit puzzled by this lazy thing. Let's say we have: void dotimes(int count, lazy void exp) { for (int i = 0; i < count; i++) { exp(); } } and I can call it like this: int x; dotimes(5, x++); And it works as expected and x end up being 5. But shouldn't I also be allowed to pass in a delegate of the appropriate type dotimes(5, {writefln(x); x++;}); A funny thing happens: nothing. The loop in dotimes does get executed 5 times but delegate passed in isn't called?
Sep 01 2006
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Ivan Senji wrote:
 Walter Bright wrote:
 
 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.

 http://www.digitalmars.com/d/changelog.html

Hmm, I am afraid I have to admit I'm a little bit puzzled by this lazy thing. Let's say we have: void dotimes(int count, lazy void exp) { for (int i = 0; i < count; i++) { exp(); } } and I can call it like this: int x; dotimes(5, x++); And it works as expected and x end up being 5. But shouldn't I also be allowed to pass in a delegate of the appropriate type dotimes(5, {writefln(x); x++;}); A funny thing happens: nothing. The loop in dotimes does get executed 5 times but delegate passed in isn't called?

This is because anonymous delegates are themselves expressions, and so your 'exp()' just evaluates to the delegate itself -- it does not invoke it. However, to achieve what you were trying to do, just make use of parentheses and the comma operator. Also, you may provide an overload that takes a lazy delegate. Here is my own test program, which worked without issue: # module lazy1 ; # # import std .stdio ; # # void dotimes (int count, lazy void exp) { # while (count--) exp(); # } # # void dotimes (int count, lazy void delegate() exp) { # while (count--) exp()(); # } # # void main () { # int x; # dotimes(5, x++); # writefln("x is now: ", x); # # int y; # dotimes(5, (writefln("[y] ", y), y++)); # writefln("y is now: ", y); # # int z; # dotimes(5, {writefln("[z] ", z); z++;}); # writefln("z is now: ", z); # } -- Chris Nicholson-Sauls
Sep 01 2006
parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Chris Nicholson-Sauls wrote:
 
 
 Ivan Senji wrote:
 Walter Bright wrote:

 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage 
 class.

 http://www.digitalmars.com/d/changelog.html

Hmm, I am afraid I have to admit I'm a little bit puzzled by this lazy thing. Let's say we have: void dotimes(int count, lazy void exp) { for (int i = 0; i < count; i++) { exp(); } } and I can call it like this: int x; dotimes(5, x++); And it works as expected and x end up being 5. But shouldn't I also be allowed to pass in a delegate of the appropriate type dotimes(5, {writefln(x); x++;}); A funny thing happens: nothing. The loop in dotimes does get executed 5 times but delegate passed in isn't called?

This is because anonymous delegates are themselves expressions, and so your 'exp()' just evaluates to the delegate itself -- it does not invoke it. However, to achieve what you were trying to do, just make use of parentheses and the comma operator. Also, you may provide an overload that takes a lazy delegate. Here is my own test program, which worked without issue:

Hmm, there is something about this lazy stuff that is troubling me and I'm not exactly sure what it is and if I can explain it: so it is x++ vs {writefln(x); x++;} The first one is an expression that looks like it is executed at call site but it isn't because that parameter is declared to be lazy. It is executed inside dotimes. That is ok. The second is a block of statements, actually it is a void delegate. It isn't executed at call site so it also will not be executed in dotimes. To make it be executed in dotimes I have to make it into something that looks like it is being executed: for example: {writefln(x); x++;}() And this is when thing begin to suck (unless I am missing something?). So if I had dotimes(5, x++); and now if I want it to do 5 times somethin a bit more than just x++ i cannot just write: dotimes(5, {writefln(); x++;}); And now a completly different function is called (one taking void delegate() as argument), to get it to call the lazy function I have to change to type from void delegate() to void by pretending to be calling the delegate. So is there a point to having lazy, I could only have written dotimes that takes void delegate() an write this: dotimes(5, {x++;}); and dotimes(5, {writefln(); x++;} ); vs dotimes(5, x++); and dotimes(5, {writefln(); x++;}() ); And now (while writing) I finally figure out what was troubling me: each of these approaches has a pretty case and an ugly case, the two pretty cases being: dotimes(5, x++); and dotimes(5, {writefln(); x++;} ); But to get that to work 2 different methods are needed. Don't feel the need to reply to this incoherent post :D , it is just some of my thoughts about lazy. Although now I understand what is happening and why, this is still troubling me.
Sep 01 2006
next sibling parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Ivan Senji wrote:
 Chris Nicholson-Sauls wrote:
 Ivan Senji wrote:
 Walter Bright wrote:

 The implicit conversion to delegate just broke too much. Instead, 
 I'm trying out Tom S.'s suggestion of using a 'lazy' parameter 
 storage class.

 http://www.digitalmars.com/d/changelog.html

Hmm, I am afraid I have to admit I'm a little bit puzzled by this lazy thing. Let's say we have: void dotimes(int count, lazy void exp) { for (int i = 0; i < count; i++) { exp(); } } and I can call it like this: int x; dotimes(5, x++); And it works as expected and x end up being 5. But shouldn't I also be allowed to pass in a delegate of the appropriate type dotimes(5, {writefln(x); x++;}); A funny thing happens: nothing. The loop in dotimes does get executed 5 times but delegate passed in isn't called?

This is because anonymous delegates are themselves expressions, and so your 'exp()' just evaluates to the delegate itself -- it does not invoke it. However, to achieve what you were trying to do, just make use of parentheses and the comma operator. Also, you may provide an overload that takes a lazy delegate. Here is my own test program, which worked without issue:

Hmm, there is something about this lazy stuff that is troubling me and I'm not exactly sure what it is and if I can explain it: so it is x++ vs {writefln(x); x++;} The first one is an expression that looks like it is executed at call site but it isn't because that parameter is declared to be lazy. It is executed inside dotimes. That is ok. The second is a block of statements, actually it is a void delegate. It isn't executed at call site so it also will not be executed in dotimes. To make it be executed in dotimes I have to make it into something that looks like it is being executed: for example: {writefln(x); x++;}() And this is when thing begin to suck (unless I am missing something?). So if I had dotimes(5, x++); and now if I want it to do 5 times somethin a bit more than just x++ i cannot just write: dotimes(5, {writefln(); x++;}); And now a completly different function is called (one taking void delegate() as argument), to get it to call the lazy function I have to change to type from void delegate() to void by pretending to be calling the delegate. So is there a point to having lazy, I could only have written dotimes that takes void delegate() an write this: dotimes(5, {x++;}); and dotimes(5, {writefln(); x++;} ); vs dotimes(5, x++); and dotimes(5, {writefln(); x++;}() ); And now (while writing) I finally figure out what was troubling me: each of these approaches has a pretty case and an ugly case, the two pretty cases being: dotimes(5, x++); and dotimes(5, {writefln(); x++;} );

Actually I just figured out i can have both pretty cases :) Hooray, just need to change dotimes to: void dotimes(int count, void delegate()[] exp...) { for (int i = 0; i < count; i++) { foreach(dg; exp) dg(); } } With the added benefit of being able to do the craziest things: dotimes(5, f++, writefln(f), f*=2); being equal to: dotimes(5, {f++; writefln(f); f*=2;}); This isn't bad afterall, but I've lost lazy on the way. (Note to self: figure out where to use lazy)
Sep 01 2006
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
Ivan Senji wrote:
 Chris Nicholson-Sauls wrote:
 Ivan Senji wrote:
 Walter Bright wrote:

 The implicit conversion to delegate just broke too much. Instead, 
 I'm trying out Tom S.'s suggestion of using a 'lazy' parameter 
 storage class.

 http://www.digitalmars.com/d/changelog.html

Hmm, I am afraid I have to admit I'm a little bit puzzled by this lazy thing. Let's say we have: void dotimes(int count, lazy void exp) { for (int i = 0; i < count; i++) { exp(); } } and I can call it like this: int x; dotimes(5, x++); And it works as expected and x end up being 5. But shouldn't I also be allowed to pass in a delegate of the appropriate type dotimes(5, {writefln(x); x++;}); A funny thing happens: nothing. The loop in dotimes does get executed 5 times but delegate passed in isn't called?

This is because anonymous delegates are themselves expressions, and so your 'exp()' just evaluates to the delegate itself -- it does not invoke it. However, to achieve what you were trying to do, just make use of parentheses and the comma operator. Also, you may provide an overload that takes a lazy delegate. Here is my own test program, which worked without issue:

Hmm, there is something about this lazy stuff that is troubling me and I'm not exactly sure what it is and if I can explain it: so it is x++ vs {writefln(x); x++;} The first one is an expression that looks like it is executed at call site but it isn't because that parameter is declared to be lazy. It is executed inside dotimes. That is ok. The second is a block of statements, actually it is a void delegate. It isn't executed at call site so it also will not be executed in dotimes. To make it be executed in dotimes I have to make it into something that looks like it is being executed: for example: {writefln(x); x++;}() And this is when thing begin to suck (unless I am missing something?). So if I had dotimes(5, x++); and now if I want it to do 5 times somethin a bit more than just x++ i cannot just write: dotimes(5, {writefln(); x++;}); And now a completly different function is called (one taking void delegate() as argument), to get it to call the lazy function I have to change to type from void delegate() to void by pretending to be calling the delegate. So is there a point to having lazy, I could only have written dotimes that takes void delegate() an write this: dotimes(5, {x++;}); and dotimes(5, {writefln(); x++;} ); vs dotimes(5, x++); and dotimes(5, {writefln(); x++;}() ); And now (while writing) I finally figure out what was troubling me: each of these approaches has a pretty case and an ugly case, the two pretty cases being: dotimes(5, x++); and dotimes(5, {writefln(); x++;} ); But to get that to work 2 different methods are needed.

It may be that delegates should be implicitly convertible to lazy expressions with the same signature. Thus: void fn( lazy int x ); Should accept both: fn( i++ ); and fn( { return i++; } ); Currently, they only accept the former. Sean
Sep 01 2006
parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Sean Kelly wrote:
 Ivan Senji wrote:
 Chris Nicholson-Sauls wrote:
 Ivan Senji wrote:
 Walter Bright wrote:

 The implicit conversion to delegate just broke too much. Instead, 
 I'm trying out Tom S.'s suggestion of using a 'lazy' parameter 
 storage class.

 http://www.digitalmars.com/d/changelog.html

Hmm, I am afraid I have to admit I'm a little bit puzzled by this lazy thing. Let's say we have: void dotimes(int count, lazy void exp) { for (int i = 0; i < count; i++) { exp(); } } and I can call it like this: int x; dotimes(5, x++); And it works as expected and x end up being 5. But shouldn't I also be allowed to pass in a delegate of the appropriate type dotimes(5, {writefln(x); x++;}); A funny thing happens: nothing. The loop in dotimes does get executed 5 times but delegate passed in isn't called?

This is because anonymous delegates are themselves expressions, and so your 'exp()' just evaluates to the delegate itself -- it does not invoke it. However, to achieve what you were trying to do, just make use of parentheses and the comma operator. Also, you may provide an overload that takes a lazy delegate. Here is my own test program, which worked without issue:

Hmm, there is something about this lazy stuff that is troubling me and I'm not exactly sure what it is and if I can explain it: so it is x++ vs {writefln(x); x++;} The first one is an expression that looks like it is executed at call site but it isn't because that parameter is declared to be lazy. It is executed inside dotimes. That is ok. The second is a block of statements, actually it is a void delegate. It isn't executed at call site so it also will not be executed in dotimes. To make it be executed in dotimes I have to make it into something that looks like it is being executed: for example: {writefln(x); x++;}() And this is when thing begin to suck (unless I am missing something?). So if I had dotimes(5, x++); and now if I want it to do 5 times somethin a bit more than just x++ i cannot just write: dotimes(5, {writefln(); x++;}); And now a completly different function is called (one taking void delegate() as argument), to get it to call the lazy function I have to change to type from void delegate() to void by pretending to be calling the delegate. So is there a point to having lazy, I could only have written dotimes that takes void delegate() an write this: dotimes(5, {x++;}); and dotimes(5, {writefln(); x++;} ); vs dotimes(5, x++); and dotimes(5, {writefln(); x++;}() ); And now (while writing) I finally figure out what was troubling me: each of these approaches has a pretty case and an ugly case, the two pretty cases being: dotimes(5, x++); and dotimes(5, {writefln(); x++;} ); But to get that to work 2 different methods are needed.

It may be that delegates should be implicitly convertible to lazy expressions with the same signature. Thus:

Maybe, that is what I expected it would do in the first place (it's too late to think now :))
 
     void fn( lazy int x );
 
 Should accept both:
 
     fn( i++ );
 
 and
 
     fn( { return i++; } );
 
 Currently, they only accept the former.

Except in a strange (but documented) feature that variadic arguments are implicitly converted to delegates (used in my reply to myself).
Sep 01 2006
prev sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Ivan Senji wrote:
 Chris Nicholson-Sauls wrote:
 
 Ivan Senji wrote:

 Walter Bright wrote:

 The implicit conversion to delegate just broke too much. Instead, 
 I'm trying out Tom S.'s suggestion of using a 'lazy' parameter 
 storage class.

 http://www.digitalmars.com/d/changelog.html

Hmm, I am afraid I have to admit I'm a little bit puzzled by this lazy thing. Let's say we have: void dotimes(int count, lazy void exp) { for (int i = 0; i < count; i++) { exp(); } } and I can call it like this: int x; dotimes(5, x++); And it works as expected and x end up being 5. But shouldn't I also be allowed to pass in a delegate of the appropriate type dotimes(5, {writefln(x); x++;}); A funny thing happens: nothing. The loop in dotimes does get executed 5 times but delegate passed in isn't called?

This is because anonymous delegates are themselves expressions, and so your 'exp()' just evaluates to the delegate itself -- it does not invoke it. However, to achieve what you were trying to do, just make use of parentheses and the comma operator. Also, you may provide an overload that takes a lazy delegate. Here is my own test program, which worked without issue:

Hmm, there is something about this lazy stuff that is troubling me and I'm not exactly sure what it is and if I can explain it: so it is x++ vs {writefln(x); x++;} The first one is an expression that looks like it is executed at call site but it isn't because that parameter is declared to be lazy. It is executed inside dotimes. That is ok. The second is a block of statements, actually it is a void delegate. It isn't executed at call site so it also will not be executed in dotimes. To make it be executed in dotimes I have to make it into something that looks like it is being executed: for example: {writefln(x); x++;}() And this is when thing begin to suck (unless I am missing something?). So if I had dotimes(5, x++); and now if I want it to do 5 times somethin a bit more than just x++ i cannot just write: dotimes(5, {writefln(); x++;}); And now a completly different function is called (one taking void delegate() as argument), to get it to call the lazy function I have to change to type from void delegate() to void by pretending to be calling the delegate. So is there a point to having lazy, I could only have written dotimes that takes void delegate() an write this: dotimes(5, {x++;}); and dotimes(5, {writefln(); x++;} ); vs dotimes(5, x++); and dotimes(5, {writefln(); x++;}() ); And now (while writing) I finally figure out what was troubling me: each of these approaches has a pretty case and an ugly case, the two pretty cases being: dotimes(5, x++); and dotimes(5, {writefln(); x++;} ); But to get that to work 2 different methods are needed. Don't feel the need to reply to this incoherent post :D , it is just some of my thoughts about lazy. Although now I understand what is happening and why, this is still troubling me.

Or... just put parentheses around it instead of braces, and use commas instead of semicolons, like I did. That works without having to do any extra work at all. (Although your typesafe variadic delegate parameter trick is pretty interesting, too.) dotimes(5, x++); dotimes(5, (writefln(x), x++)); -- Chris Nicholson-Sauls
Sep 02 2006
prev sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
So there is IFTI for member functions functions now...I'm a little late, 
but thank you and Oskar Linde!! This is amazing. Also the lazy thing, 
it's great.

Walter Bright wrote:
 The implicit conversion to delegate just broke too much. Instead, I'm 
 trying out Tom S.'s suggestion of using a 'lazy' parameter storage class.
 
 http://www.digitalmars.com/d/changelog.html

Sep 03 2006