digitalmars.D - Static Const (Compile-Time) Functions
- AJG (35/35) Jul 15 2005 Hi there,
-
Jarrett Billingsley
(17/17)
Jul 15 2005
"AJG"
wrote in message - AJG (8/25) Jul 15 2005 Hm... interesting. I didn't know you could do that. Thanks for the sugge...
- Jarrett Billingsley (8/45) Jul 15 2005 Nope. You can use it as many times as you'd like. I use this weird for...
- AJG (5/53) Jul 15 2005 No, I meant that the template itself is just one initialization. There i...
- Jarrett Billingsley (8/13) Jul 17 2005 Ah, yes, I see what you mean. You wouldn't be able to, say, calculate a...
- AJG (9/15) Jul 17 2005 Yeah, I'm finding out more and more exotic uses for templates... this wo...
- BCS (43/46) Jul 18 2005 ..
- David Medlock (23/87) Jul 19 2005 Would it not be easier just to store the value as one quantity, say
- BCS (15/37) Jul 19 2005 Yes, that would be more convenient if I was only dealing with distances....
- David Medlock (13/65) Jul 19 2005 Why not make a Force struct for Newtons? Then they cannot be added
- BCS (8/19) Jul 19 2005 The class solution would be slower (but would allow runtime units). As t...
- BCS (12/13) Jul 19 2005 ..
- Andrew Fedoniouk (3/20) Jul 15 2005 Nice idea!
- Jarrett Billingsley (4/5) Jul 17 2005 Thank Andy Friesen, he's the one who showed me how to do this :)
Hi there, In the vein of the const parameter discussion, I would like to introduce this topic. Since some form of const is coming, it would be great if it was made to support static const functions at some point. Anyway, these functions run at compile time. They can return a true const which would be identical to a const literal. I don't think they exist in C++, but C++ does have plain const functions. This is not the same thing (it's better). This is essentially an extremely safe, full-featured macro. For example: I'm not suggesting any specific syntax, just the general idea. Is this something that could be done? Some benefits: - It doesn't add _anything_ to the runtime. - Doesn't require any runtime or library support. - Can make your code faster and smaller by shifting some processing to compile-time. - No new concepts or keywords needed. Functions and consts already exist in D. This simply combines the two. - Can make your code cleaner and more readable without incurring any function-call penalties. - You get the best of both worlds: macro zero-cost efficiency, plus complete function safety and (hehehe) functionality. Thanks, --AJG.
Jul 15 2005
"AJG" <AJG_member pathlink.com> wrote in message news:db8r7q$2k3u$1 digitaldaemon.com... Something like this can already be done with templates, although with a more.. obtuse syntax. template square(T, T value) { const T square=(value*value); } void main() { int x=square!(int,5); writefln(x); } Since the template is expanded at compile-time, the constant folds, and x=25. The square!() template can also be used to initialize global or const members. A more function-esque syntax would be welcome, though.
Jul 15 2005
Hm... interesting. I didn't know you could do that. Thanks for the suggestion. The problem is (other than being template-syntax-clunky), that you are still limited to one initialization. In essense you are just moving it somewhere else. I'll definitely use it, but it'd be great to have real const functions with normal syntax and features. Walter, before I get my hopes up, is this even technically possible? --AJG. In article <db8ssg$2mjj$1 digitaldaemon.com>, Jarrett Billingsley says..."AJG" <AJG_member pathlink.com> wrote in message news:db8r7q$2k3u$1 digitaldaemon.com... Something like this can already be done with templates, although with a more.. obtuse syntax. template square(T, T value) { const T square=(value*value); } void main() { int x=square!(int,5); writefln(x); } Since the template is expanded at compile-time, the constant folds, and x=25. The square!() template can also be used to initialize global or const members. A more function-esque syntax would be welcome, though.
Jul 15 2005
"AJG" <AJG_member pathlink.com> wrote in message news:db9o29$gij$1 digitaldaemon.com...The problem is (other than being template-syntax-clunky), that you are still limited to one initialization. In essense you are just moving it somewhere else.Nope. You can use it as many times as you'd like. I use this weird form of templates to replace function-style macros from C headers that are used to initialize module-level variables or constants. const int x=square!(int,5); const int y=square!(int,10); const float z=square!(float,3.14159);I'll definitely use it, but it'd be great to have real const functions with normal syntax and features. Walter, before I get my hopes up, is this even technically possible? --AJG. In article <db8ssg$2mjj$1 digitaldaemon.com>, Jarrett Billingsley says..."AJG" <AJG_member pathlink.com> wrote in message news:db8r7q$2k3u$1 digitaldaemon.com... Something like this can already be done with templates, although with a more.. obtuse syntax. template square(T, T value) { const T square=(value*value); } void main() { int x=square!(int,5); writefln(x); } Since the template is expanded at compile-time, the constant folds, and x=25. The square!() template can also be used to initialize global or const members. A more function-esque syntax would be welcome, though.
Jul 15 2005
Hi,"AJG" <AJG_member pathlink.com> wrote in message news:db9o29$gij$1 digitaldaemon.com...No, I meant that the template itself is just one initialization. There is no other useful construct that you could use (e.g. a static if). I mean, the whole thing has to be one single assignment expression, right? --AJG.The problem is (other than being template-syntax-clunky), that you are still limited to one initialization. In essense you are just moving it somewhere else.Nope. You can use it as many times as you'd like. I use this weird form of templates to replace function-style macros from C headers that are used to initialize module-level variables or constants.const int x=square!(int,5); const int y=square!(int,10); const float z=square!(float,3.14159);I'll definitely use it, but it'd be great to have real const functions with normal syntax and features. Walter, before I get my hopes up, is this even technically possible? --AJG. In article <db8ssg$2mjj$1 digitaldaemon.com>, Jarrett Billingsley says..."AJG" <AJG_member pathlink.com> wrote in message news:db8r7q$2k3u$1 digitaldaemon.com... Something like this can already be done with templates, although with a more.. obtuse syntax. template square(T, T value) { const T square=(value*value); } void main() { int x=square!(int,5); writefln(x); } Since the template is expanded at compile-time, the constant folds, and x=25. The square!() template can also be used to initialize global or const members. A more function-esque syntax would be welcome, though.
Jul 15 2005
"AJG" <AJG_member pathlink.com> wrote in message news:dba07g$ll2$1 digitaldaemon.com...No, I meant that the template itself is just one initialization. There is no other useful construct that you could use (e.g. a static if). I mean, the whole thing has to be one single assignment expression, right?Ah, yes, I see what you mean. You wouldn't be able to, say, calculate a factorial with this (though that can strangely be done with templates as well..). I'm not sure how complex it would be, however, to evaluate compile-time functions, as they'd have to be compiled and run _during_ the compilation process. I don't know if that's even possible.
Jul 17 2005
Hi,Ah, yes, I see what you mean. You wouldn't be able to, say, calculate a factorial with this (though that can strangely be done with templates as well..).Yeah, I'm finding out more and more exotic uses for templates... this would all get much better if implicit instantiation were possible.I'm not sure how complex it would be, however, to evaluate compile-time functions, as they'd have to be compiled and run _during_ the compilation process. I don't know if that's even possible.I have a feeling this is related to the halting problem. However, I don't think it's hopeless. I think you would only have to deal with a small, limited subset of all possible inputs (namely, constant inputs). Can anyone who knows about this pitch in? Thanks, --AJG.
Jul 17 2005
In article <dbeh1t$12p4$1 digitaldaemon.com>, AJG says... ..Yeah, I'm finding out more and more exotic uses for templates... this would all get much better if implicit instantiation were possible...--AJG.While we are whishing, how about implicit instantiation defining the return type of a function as a function of the inputs. That would allow something like this: #template Unit(T, int d, int m, int t) Unit!(T,d2,m2,t2).Unit v2) Unit!(T,d2,m2,t2).Unit v2) I know, I know, implementing this would likely be a royal mess. One possible means to simplify it would be to require a list of allowed instantiations e.g. BCS p.s One quirk of the above example is that it can optimize to the same code you would get with using just reals.
Jul 18 2005
BCS wrote:In article <dbeh1t$12p4$1 digitaldaemon.com>, AJG says... ..Would it not be easier just to store the value as one quantity, say meters and use member functions to store/retrieve? I do something like this in my programs already, and its more readable. struct Length // stored in meters { float units = 0; float meters() { return units; } float meters( float f ) { return units = f; } float feet() { return meters * FeetPerMeter; } float feet( float v ) { return units = ( v / FeetPerMeter ); } ... Length opAdd( Length L ) { Length tmp; tmp.units = this.units + L.units; return tmp; } } Length a,b,c; a.feet = 20; b.meters = 15; c = a + b; -DavidMYeah, I'm finding out more and more exotic uses for templates... this would all get much better if implicit instantiation were possible...--AJG.While we are whishing, how about implicit instantiation defining the return type of a function as a function of the inputs. That would allow something like this: #template Unit(T, int d, int m, int t) Unit!(T,d2,m2,t2).Unit v2) Unit!(T,d2,m2,t2).Unit v2) I know, I know, implementing this would likely be a royal mess. One possible means to simplify it would be to require a list of allowed instantiations e.g. BCS p.s One quirk of the above example is that it can optimize to the same code you would get with using just reals.
Jul 19 2005
Would it not be easier just to store the value as one quantity, say meters and use member functions to store/retrieve? I do something like this in my programs already, and its more readable. struct Length // stored in meters { float units = 0; float meters() { return units; } float meters( float f ) { return units = f; } float feet() { return meters * FeetPerMeter; } float feet( float v ) { return units = ( v / FeetPerMeter ); } ... Length opAdd( Length L ) { Length tmp; tmp.units = this.units + L.units; return tmp; } } Length a,b,c; a.feet = 20; b.meters = 15; c = a + b; -DavidMYes, that would be more convenient if I was only dealing with distances. However it would allow something like the following to compile: Distance a, b, c; a.meters = 15; b.Newtons = 5 c = a + b; Meters plus Newtons is not only meaningless, it is invalid. The template construct that I suggested, would ensure that only Unit of similar types can be added. It would also ensure that all other math operations result in the right type of unit. One solution that I have considered acutely implementing is vary similar to what I suggested, but done as a class with all of the checks done at runtime and the dimensions carried along with the value in an object. It would have significant runtime overhead where as the template method would run as fast as using just bare reals.
Jul 19 2005
BCS wrote:Why not make a Force struct for Newtons? Then they cannot be added together. The type system already supports this type of checking. As a matter of fact you could do things like: Velocity v; Time t; Distance d; d.meters = 100; t.seconds = 10; v = m / t;Would it not be easier just to store the value as one quantity, say meters and use member functions to store/retrieve? I do something like this in my programs already, and its more readable. struct Length // stored in meters { float units = 0; float meters() { return units; } float meters( float f ) { return units = f; } float feet() { return meters * FeetPerMeter; } float feet( float v ) { return units = ( v / FeetPerMeter ); } ... Length opAdd( Length L ) { Length tmp; tmp.units = this.units + L.units; return tmp; } } Length a,b,c; a.feet = 20; b.meters = 15; c = a + b; -DavidMYes, that would be more convenient if I was only dealing with distances. However it would allow something like the following to compile: Distance a, b, c; a.meters = 15; b.Newtons = 5 c = a + b; Meters plus Newtons is not only meaningless, it is invalid. The template construct that I suggested, would ensure that only Unit of similar types can be added. It would also ensure that all other math operations result in the right type of unit.One solution that I have considered acutely implementing is vary similar to what I suggested, but done as a class with all of the checks done at runtime and the dimensions carried along with the value in an object. It would have significant runtime overhead where as the template method would run as fast as using just bare reals.I dont see your solution being any faster, except for possible constants(compile time). My above code will optimize down to just reals. -DavidM
Jul 19 2005
In article <dbjigh$hva$1 digitaldaemon.com>, David Medlock says...Why not make a Force struct for Newtons? Then they cannot be added together. The type system already supports this type of checking.see my last post (they crossed in cyber space)One solution that I have considered acutely implementing is vary similar to what I suggested, but done as a class with all of the checks done at runtime and the dimensions carried along with the value in an object. It would have significant runtime overhead where as the template method would run as fast as using just bare reals.I dont see your solution being any faster, except for possible constants(compile time). My above code will optimize down to just reals. -DavidMThe class solution would be slower (but would allow runtime units). As to the template solution, its advantage over the structs is not speed (I agree they would run at the same speed) but implementation. It is one typedef where the structs would require anywhere from about 5 or 6 to upwards of 50 different types of structs depending on what you are doing. On the other hand it requires a lot more from the compiler.
Jul 19 2005
In article <dbjeca$ejm$1 digitaldaemon.com>, BCS says...Yes, that would be more convenient if I was only dealing with distances... I just looked again at what you proposed and noticed that it explicitly deals with length. My bad, (:P) that makes about half of my last post junk. On the other hand, that solution requires a different struct to be declared for each type of unit that is going to be used. This vary quickly gets impractical, one quick google search found a list of about twenty categories of BASIC units, not even getting into things like the units of the various constants. Addition is bad enough, but multiplication quickly turns into a nightmare. For things that don’t use to many units, using structs would be just fine, however I tend to end up using more complicated units and would like something a bit more flexible
Jul 19 2005
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:db8ssg$2mjj$1 digitaldaemon.com..."AJG" <AJG_member pathlink.com> wrote in message news:db8r7q$2k3u$1 digitaldaemon.com... Something like this can already be done with templates, although with a more.. obtuse syntax. template square(T, T value) { const T square=(value*value); } void main() { int x=square!(int,5); writefln(x); } Since the template is expanded at compile-time, the constant folds, and x=25. The square!() template can also be used to initialize global or const members. A more function-esque syntax would be welcome, though.Nice idea!
Jul 15 2005
"Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:dba2cb$nu6$1 digitaldaemon.com...Nice idea!Thank Andy Friesen, he's the one who showed me how to do this :) Templates are weird.
Jul 17 2005