www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - define should be the keyword for manifest constants

reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
Seriously.  Are we too concerned about stigmas to not use the absolute best 
word for defining a constant?  Even in the description of a manifest 
constant, it will be something like:

to *define* a manifest constant, use enum

If you use *define* you don't even need an explanation!

If you are concerned about people not liking define because it *looks* too 
much like C's #define, then lets also drop goto (because C's is just too 
error prone), class (because there are slicing problems in C++, and we don't 
want people to think they still exist in D), struct (because C++'s is just 
like class, so people will think D structs and classes are the same), etc.

If you are concerned about adding a new keyword, please, all coders who have 
used the symbol define, please respond to this thread, and we'll send you a 
handy script that will update your code to use another keyword of your 
choice.  Only $6.95 shipping and handling.

-Steve 
Dec 13 2007
next sibling parent reply Gilles G. <schaouette free.fr> writes:
"define" makes no sense if you want to declare a "const" member function.
It could be of great use for manifest constant, but you'd still have to find a
word for other const cases...

Steven Schveighoffer Wrote:

 Seriously.  Are we too concerned about stigmas to not use the absolute best 
 word for defining a constant?  Even in the description of a manifest 
 constant, it will be something like:
 
 to *define* a manifest constant, use enum
 
 If you use *define* you don't even need an explanation!
 
 If you are concerned about people not liking define because it *looks* too 
 much like C's #define, then lets also drop goto (because C's is just too 
 error prone), class (because there are slicing problems in C++, and we don't 
 want people to think they still exist in D), struct (because C++'s is just 
 like class, so people will think D structs and classes are the same), etc.
 
 If you are concerned about adding a new keyword, please, all coders who have 
 used the symbol define, please respond to this thread, and we'll send you a 
 handy script that will update your code to use another keyword of your 
 choice.  Only $6.95 shipping and handling.
 
 -Steve 
 
 

Dec 13 2007
next sibling parent reply Jason House <jason.james.house gmail.com> writes:
Gilles G. Wrote:

 "define" makes no sense if you want to declare a "const" member function.
 It could be of great use for manifest constant, but you'd still have to find a
word for other const cases...

I have absolutely no problem with different logical things using different keywords. IMHO, shoe-horning keywords to fit a new and unanticipated case is not desirable. I'd hate to see manifest constants without types. I'd probably vote against define simply because I associate it with a loss of type info (probably the influence of C) I'm not yet convinced in what cases manifest constants are important. I think most headers defining integral constants should be enums instead of (C) #define. That's probably one reason the enum keyword gained some traction. If manifest constants go beyond integral types, is it better to extend enums to contain more types than just integer? Or is it better to use another keyword? I kind of like the pure proposal because it does fit in with the concept of pure functions. With the whole const vs. invariant thing, even const as a keyword doesn't make a whole lot of sense (it'd really be invariant). Of course, I wonder why the compiler can't just determine which constants should be manifest and which need allocation. It could very well be that we just say define manifest constants like any other constants and then *if* you don't trust the compiler to get it right, use an attribute to force the compiler in the right direction. manifest{ const int A = ...; const int B = ...; const int C = ...; ... }
Dec 13 2007
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Jason House"  wrote
 Gilles G. Wrote:

 "define" makes no sense if you want to declare a "const" member function.
 It could be of great use for manifest constant, but you'd still have to 
 find a word for other const cases...

I have absolutely no problem with different logical things using different keywords. IMHO, shoe-horning keywords to fit a new and unanticipated case is not desirable. I'd hate to see manifest constants without types. I'd probably vote against define simply because I associate it with a loss of type info (probably the influence of C)

define int x = 0; What's wrong with that?
 I'm not yet convinced in what cases manifest constants are important.  I 
 think most headers defining integral constants should be enums instead of 
 (C) #define.  That's probably one reason the enum keyword gained some 
 traction.

They are important because they occupy code space if they are not used. For example, if you have 10,000 constants defined in a module, but you only need 10 of them, then your code now has 10,000 constants in it, whereas if you define 10,000 manifest constants, only the ones you use are included because they are inlined in the code.
 If manifest constants go beyond integral types, is it better to extend 
 enums to contain more types than just integer?  Or is it better to use 
 another keyword?

enum does not capture what we are trying to do. We are trying to make an instance of a certain type into a manifest constant, not define a new type.
I kind of like the pure proposal because it does fit in with the concept of 
pure functions.

I like pure more than enum, but the issue I have with pure is that a pure struct that has methods would imply only pure methods could be called. Of course, having a manifest constant struct would mean there would be no address to pass to a member function, but people have suggested that one can make a copy of the struct on the stack and then call the method on that. In any case, pure would be acceptable to me, but it really doesn't make any intuitive sense. If you had never heard of functionali programming and pure functions, and you read a D file that had: pure x = 0; What would you think pure means?
With the whole const vs. invariant thing, even const as a keyword doesn't 
make a whole lot of sense (it'd really be invariant).

 Of course, I wonder why the compiler can't just determine which constants 
 should be manifest and which need allocation.  It could very well be that 
 we just say define manifest constants like any other constants and then 
 *if* you don't trust the compiler to get it right, use an attribute to 
 force the compiler in the right direction.

How would the compiler know when compiling a module with a constant whether some other module is going to take the address of that constant? Plus it is nice to be able to FORCE the compiler to say "you can't use this like a non-manifest constant" But I do agree that it would be nice if the compiler could optimize when possible. -Steve
Dec 13 2007
next sibling parent reply guslay <guslay gmail.com> writes:
Janice Caron Wrote:

 On 12/13/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 How would the compiler know when compiling a module with a constant whether
 some other module is going to take the address of that constant?

You're thinking old-school. D is new-school. Imports don't just import symbols, they import abstract symbol trees. Saying "How would the compiler know when compiling a module with a constant whether some other module is going to take the address of that constant?" is like saying "How would the compiler know whether a template needs to be instantiated?". The point is, it doesn't need to - it just exports the AST. In fact, you can mimic #define pi=3.14159 as template pi { const real pi = 3.14159 } in one module, and it will take up zero storage space until someone (possibly in another module) instantiates it with something like real x = pi!; Not that I'm suggesting that we use templates for compile-time constants! (That would be silly). But the fact that we can do it at all shows that it can be done.

1 - Code: const real Pi = 3.14; // or the template version. //... real x = Pi; 2 - Compiler: Pi is const. Replace x dynamic initialisation with static init. Becomes real x = 3.14; 3 - All value assigment of Pi have been trivialy optimized away. Pi is not used anymore. However, if Pi is addressable, someone in another module might have taken a reference to Pi. The compiler cannot know. Therefore, Pi cannot be optimized way. This is what take storage. If Pi is "enum"-like, it's a symbol that is just a placeholder for a value. After its value has been propagated, is not required anymore. It does not take storage.
Dec 13 2007
parent =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

guslay wrote:
 Janice Caron Wrote:
 
 On 12/13/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 How would the compiler know when compiling a module with a constant whether
 some other module is going to take the address of that constant?

symbols, they import abstract symbol trees. Saying "How would the compiler know when compiling a module with a constant whether some other module is going to take the address of that constant?" is like saying "How would the compiler know whether a template needs to be instantiated?". The point is, it doesn't need to - it just exports the AST. In fact, you can mimic #define pi=3.14159 as template pi { const real pi = 3.14159 } in one module, and it will take up zero storage space until someone (possibly in another module) instantiates it with something like real x = pi!; Not that I'm suggesting that we use templates for compile-time constants! (That would be silly). But the fact that we can do it at all shows that it can be done.

1 - Code: const real Pi = 3.14; // or the template version. //... real x = Pi; 2 - Compiler: Pi is const. Replace x dynamic initialisation with static init. Becomes real x = 3.14; 3 - All value assigment of Pi have been trivialy optimized away. Pi is not used anymore. However, if Pi is addressable, someone in another module might have taken a reference to Pi. The compiler cannot know. Therefore, Pi

 be optimized way. This is what take storage.
 

module does not take the address of Pi, then the compiler does not allocate any storage for it. If this module does take the address of Pi, then the compiler allocates storage in a special section. Then, when the linker creates the final executable, it can combine all allocations for Pi into a single one. This is actually what already happens for template functions (and now that I think about it, it's probably what happens for Janice's Pi template too... Jerome - -- +------------------------- Jerome M. BERGER ---------------------+ | mailto:jeberger free.fr | ICQ: 238062172 | | http://jeberger.free.fr/ | Jabber: jeberger jabber.fr | +---------------------------------+------------------------------+ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHYYu0d0kWM4JG3k8RAkDsAKCejovzcBcqPEBae0HCySXDbLYx9QCgg5lM rCU59t/Lr690482Um2+zwxg= =NLyG -----END PGP SIGNATURE-----
Dec 13 2007
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Janice Caron" wrote
 On 12/13/07, Steven Schveighoffer wrote:
 How would the compiler know when compiling a module with a constant 
 whether
 some other module is going to take the address of that constant?

You're thinking old-school. D is new-school. Imports don't just import symbols, they import abstract symbol trees. Saying "How would the compiler know when compiling a module with a constant whether some other module is going to take the address of that constant?" is like saying "How would the compiler know whether a template needs to be instantiated?". The point is, it doesn't need to - it just exports the AST.

OK, so what is the big deal then? Why do we need manifest constants? I assume this is a problem because we are talking about fixing it. I was assuming that Jason's proposed solution (the compiler decides when to have manifest constants and when to have addressable constants) was impossible, and that the reason it is good to have manifest constants is because otherwise the compiler creates space for all non-manifest constants. Is this not the case? If not, why have a difference between manifest constant declarations and normal constant declarations? And if I'm not mistaken, import imports source code, just like #include included header files... -Steve
Dec 13 2007
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Gilles G." wrote
 "define" makes no sense if you want to declare a "const" member function.

I was not talking about using define instead of pure for *everything* that pure is for. Use pure for function declarations. Use define for manifest constants.
 It could be of great use for manifest constant, but you'd still have to 
 find a word for other const cases...

what's wrong with the current keywords? const, invariant, pure, etc? I'm talking about having define *only* for manifest constants, and nothing else. Every once in a while, there comes a time where a new keyword not only makes sense, but is the only true fit. I believe this is one of those times. -Steve
Dec 13 2007
prev sibling next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/13/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 How would the compiler know when compiling a module with a constant whether
 some other module is going to take the address of that constant?

You're thinking old-school. D is new-school. Imports don't just import symbols, they import abstract symbol trees. Saying "How would the compiler know when compiling a module with a constant whether some other module is going to take the address of that constant?" is like saying "How would the compiler know whether a template needs to be instantiated?". The point is, it doesn't need to - it just exports the AST. In fact, you can mimic #define pi=3.14159 as template pi { const real pi = 3.14159 } in one module, and it will take up zero storage space until someone (possibly in another module) instantiates it with something like real x = pi!; Not that I'm suggesting that we use templates for compile-time constants! (That would be silly). But the fact that we can do it at all shows that it can be done.
Dec 13 2007
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/13/07, guslay <guslay gmail.com> wrote:
 If Pi is "enum"-like, it's a symbol that is just a placeholder for a value.
After its value has been propagated, is not required anymore. It does not take
storage.

Now you're stating the obvious! :-) (And in such a patient, explanatory way, too!) I really hope you're not imagining that anyone on this thread doesn't know that.
Dec 13 2007
prev sibling next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Steven Schveighoffer wrote:
 Seriously.  Are we too concerned about stigmas to not use the absolute best 
 word for defining a constant?  Even in the description of a manifest 
 constant, it will be something like:
 
 to *define* a manifest constant, use enum
 
 If you use *define* you don't even need an explanation!
 
 If you are concerned about people not liking define because it *looks* too 
 much like C's #define, then lets also drop goto (because C's is just too 
 error prone), class (because there are slicing problems in C++, and we don't 
 want people to think they still exist in D), struct (because C++'s is just 
 like class, so people will think D structs and classes are the same), etc.

Instead of goto, let's use comefrom: foreach (a; collection) { if (a.someproperty) { found: } } throw new Exception("didn't find it!"); comefrom found; Instead of class, caste. Instead of struct, skel (short for skeleton). 'new' becomes 'makemea': auto sandwich = makemea Sandwich;
 If you are concerned about adding a new keyword, please, all coders who have 
 used the symbol define, please respond to this thread, and we'll send you a 
 handy script that will update your code to use another keyword of your 
 choice.  Only $6.95 shipping and handling.

Replacing variables and types that collide with keywords using ANOTHER keyword? That's just begging the question!
Dec 13 2007
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Christopher Wright" wrote
 Steven Schveighoffer wrote:
 If you are concerned about adding a new keyword, please, all coders who 
 have used the symbol define, please respond to this thread, and we'll 
 send you a handy script that will update your code to use another keyword 
 of your choice.  Only $6.95 shipping and handling.

Replacing variables and types that collide with keywords using ANOTHER keyword? That's just begging the question!

Oh yeah :) It was *obvious* that when I said 'use another keyword', I meant 'use another symbol'. I was just testing you to see if you'd catch that. -Steve
Dec 13 2007
prev sibling parent reply Russell Lewis <webmaster villagersonline.com> writes:
I thought about suggesting this, but what turned me off to it was this 
declaration:

	define int x = some_compile_time_func();

A C/C++ programmer will probably think of this as a #define-style 
substitution, which means that he will expect the function to run every 
time that he uses the constant.  However, what we are trying to declare 
is a manifest constant.  It seemed like it would introduce confusion.

Just my $.02,
	Russ
Dec 13 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Russell Lewis wrote:
 I thought about suggesting this, but what turned me off to it was this 
 declaration:
 
     define int x = some_compile_time_func();
 
 A C/C++ programmer will probably think of this as a #define-style 
 substitution, which means that he will expect the function to run every 
 time that he uses the constant.  However, what we are trying to declare 
 is a manifest constant.  It seemed like it would introduce confusion.

That may be their first guess as to what it does, but it doesn't seem like it would be difficult to relieve oneself of that misconception. And in any case, the only time the above would work is if some_compile_time_function() really is a compile time function. So it doesn't really matter if the user wants to think of it as evaluating every time it's used or just once. That's the whole point of compile_time / pure functions. No side effects and context doesn't matter. --bb
Dec 13 2007
parent reply Russell Lewis <webmaster villagersonline.com> writes:
Bill Baxter wrote:
 Russell Lewis wrote:
 I thought about suggesting this, but what turned me off to it was this 
 declaration:

     define int x = some_compile_time_func();

 A C/C++ programmer will probably think of this as a #define-style 
 substitution, which means that he will expect the function to run 
 every time that he uses the constant.  However, what we are trying to 
 declare is a manifest constant.  It seemed like it would introduce 
 confusion.

That may be their first guess as to what it does, but it doesn't seem like it would be difficult to relieve oneself of that misconception. And in any case, the only time the above would work is if some_compile_time_function() really is a compile time function. So it doesn't really matter if the user wants to think of it as evaluating every time it's used or just once. That's the whole point of compile_time / pure functions. No side effects and context doesn't matter.

I'm certainly not one who argues that we should take things from C/C++ without reconsidering them! :) I am just of the opinion that if we have some other good choice for the keyword ("pure"), it is desirable not to cause confusion. IMHO, it's better for a C++ programmer to say "I've never seen that keyword, let me look up what it does," than to say "I know what that does" - and be wrong. Yes, you can re-teach them. But if the keyword is unfamiliar, then you re-teach them the *first* time that they see it, not ages later when they stumble upon a subtle bug. Russ
Dec 13 2007
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 13 Dec 2007 15:13:11 -0700, Russell Lewis wrote:

 Bill Baxter wrote:
 Russell Lewis wrote:
 I thought about suggesting this, but what turned me off to it was this 
 declaration:

     define int x = some_compile_time_func();

 A C/C++ programmer will probably think of this as a #define-style 
 substitution, which means that he will expect the function to run 
 every time that he uses the constant.  However, what we are trying to 
 declare is a manifest constant.  It seemed like it would introduce 
 confusion.

That may be their first guess as to what it does, but it doesn't seem like it would be difficult to relieve oneself of that misconception. And in any case, the only time the above would work is if some_compile_time_function() really is a compile time function. So it doesn't really matter if the user wants to think of it as evaluating every time it's used or just once. That's the whole point of compile_time / pure functions. No side effects and context doesn't matter.

I'm certainly not one who argues that we should take things from C/C++ without reconsidering them! :) I am just of the opinion that if we have some other good choice for the keyword ("pure"), it is desirable not to cause confusion. IMHO, it's better for a C++ programmer to say "I've never seen that keyword, let me look up what it does," than to say "I know what that does" - and be wrong. Yes, you can re-teach them. But if the keyword is unfamiliar, then you re-teach them the *first* time that they see it, not ages later when they stumble upon a subtle bug.

Right ... like static, const, final, int, long, struct ... all used in C/C++ but not in quite the same way. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Dec 13 2007
parent Russell Lewis <webmaster villagersonline.com> writes:
Derek Parnell wrote:
 On Thu, 13 Dec 2007 15:13:11 -0700, Russell Lewis wrote:
 
 Bill Baxter wrote:
 Russell Lewis wrote:
 I thought about suggesting this, but what turned me off to it was this 
 declaration:

     define int x = some_compile_time_func();

 A C/C++ programmer will probably think of this as a #define-style 
 substitution, which means that he will expect the function to run 
 every time that he uses the constant.  However, what we are trying to 
 declare is a manifest constant.  It seemed like it would introduce 
 confusion.

like it would be difficult to relieve oneself of that misconception. And in any case, the only time the above would work is if some_compile_time_function() really is a compile time function. So it doesn't really matter if the user wants to think of it as evaluating every time it's used or just once. That's the whole point of compile_time / pure functions. No side effects and context doesn't matter.

without reconsidering them! :) I am just of the opinion that if we have some other good choice for the keyword ("pure"), it is desirable not to cause confusion. IMHO, it's better for a C++ programmer to say "I've never seen that keyword, let me look up what it does," than to say "I know what that does" - and be wrong. Yes, you can re-teach them. But if the keyword is unfamiliar, then you re-teach them the *first* time that they see it, not ages later when they stumble upon a subtle bug.

Right ... like static, const, final, int, long, struct ... all used in C/C++ but not in quite the same way.

True. But we can make any new features the "right" way (if you guys agree that my way is the "right" way, of course!) :)
Dec 13 2007
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Russell Lewis" wrote
 IMHO, it's better for a C++ programmer to say "I've never seen that 
 keyword, let me look up what it does," than to say "I know what that 
 does" - and be wrong.  Yes, you can re-teach them.  But if the keyword is 
 unfamiliar, then you re-teach them the *first* time that they see it, not 
 ages later when they stumble upon a subtle bug.

If I'm not mistaken, pure is a keyword in gcc already, and does not mean "manifest constant" -Steve
Dec 14 2007
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Russell Lewis" wrote
I thought about suggesting this, but what turned me off to it was this 
declaration:

 define int x = some_compile_time_func();

 A C/C++ programmer will probably think of this as a #define-style 
 substitution, which means that he will expect the function to run every 
 time that he uses the constant.  However, what we are trying to declare is 
 a manifest constant.  It seemed like it would introduce confusion.

 Just my $.02,
 Russ

Too bad, so sad. If you want something that acts exactly like C, use C. D already uses lots of C keywords differently than C does, that was my original point. And Bill Baxter's point is right on. If the function is compile time, no need to execute it every time it's used because the result will already be evaluated by the compiler. -Steve
Dec 13 2007
prev sibling parent "Vladimir Panteleev" <thecybershadow gmail.com> writes:
On Thu, 13 Dec 2007 22:43:41 +0200, Bill Baxter <dnewsgroup billbaxter.c=
om> wrote:

 Russell Lewis wrote:
 I thought about suggesting this, but what turned me off to it was thi=


 declaration:

     define int x =3D some_compile_time_func();

 A C/C++ programmer will probably think of this as a #define-style
 substitution, which means that he will expect the function to run eve=


 time that he uses the constant.  However, what we are trying to decla=


 is a manifest constant.  It seemed like it would introduce confusion.=


 That may be their first guess as to what it does, but it doesn't seem
 like it would be difficult to relieve oneself of that misconception.

 And in any case, the only time the above would work is if
 some_compile_time_function() really is a compile time function.  So it=

 doesn't really matter if the user wants to think of it as evaluating
 every time it's used or just once.  That's the whole point of
 compile_time / pure functions.  No side effects and context doesn't ma=

In that case, what's wrong with "alias"? It sounds good, it has the same= problem (misconception of substitution), but isn't a new keyword. -- = Best regards, Vladimir mailto:thecybershadow gmail.com
Dec 13 2007