www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Constants, Aliases

reply Xinok <xnknet gmail.com> writes:
In C++, you can define a constant by using a preprocessor:
#define INT 30

In D, the standard is to use 'const':
const int INT = 30;

The problem with the const keyword is it doesn't guarantee the expression will
be constant.
const int* PTR = new int; // This technically isn't a constant, the compiler
just doesn't allow you to modify it's value.

Another solution is to use enumerators, but they don't aloow any type other
than int:
enum { val = 30 } // OK
enum { str = "Hello" } // Error


So I was thinking, why not give this job to aliases? Aliases must be constant,
you can use any type with them, and they're easy to write.
alias 30 VAL;
alias "Hello" STR;
alias 31.5 DEC;

Expressions can simply be put within parenthesis:
alias (15 * 99) EXP;
Dec 13 2006
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Xinok wrote:
 In C++, you can define a constant by using a preprocessor:
 #define INT 30
 
 In D, the standard is to use 'const':
 const int INT = 30;
 
 The problem with the const keyword is it doesn't guarantee the expression will
 be constant.
 const int* PTR = new int; // This technically isn't a constant, the compiler
 just doesn't allow you to modify it's value.
 
 Another solution is to use enumerators, but they don't aloow any type other
 than int:
 enum { val = 30 } // OK
 enum { str = "Hello" } // Error
 
 
 So I was thinking, why not give this job to aliases? Aliases must be constant,
 you can use any type with them, and they're easy to write.
 alias 30 VAL;
 alias "Hello" STR;
 alias 31.5 DEC;
 
 Expressions can simply be put within parenthesis:
 alias (15 * 99) EXP;

It would also make writing recursive templates a little bit simpler. Sometimes it takes me a minute to figure out whether I need alias template_name[1..$] template_name; or const Type template_name = template_name[1..$]; Actually... I guess they're interchangeable till you get to the base case -- ferinstance: template tuple_all_of(T, S...) { static if(S.length == 0) { const bool tuple_all_of = true; } else static if( is(S[0]: T) ) { // either version is ok here //const bool tuple_all_of = tuple_all_of!(T, S[1..$]); alias tuple_all_of!(T, S[1..$]) tuple_all_of; } else { const bool tuple_all_of = false; } } --bb
Dec 13 2006
prev sibling next sibling parent reply nazo <lovesyao gmail.com> writes:
Expressions! Expressions!  (/ ~.)/

I think that the exchange of parameters of alias is necessary from:
   alias (x*2) exp;
to:
   alias exp=x*2;

And I need alias arguments as syntax sugar like:
   alias(alias i) exp=i*2;
same as:
   template exp(alias i){
     alias exp=i*2;
   }

#sorry for my poor English.
Dec 14 2006
next sibling parent nazo <lovesyao gmail.com> writes:
current:
void func(){}
alias func test;

suggestion:
void func(){}
alias test=func;

alias test2="test";

#this code is error yet
import std.typetuple,std.stdio;
void func(){writefln("test");}
alias TypeTuple!(func) test;
void main(){
   test[0]();//error
}
#And this too
import std.typetuple,std.stdio;
int x;
alias TypeTuple!(x*x) test;
void main(){
   x=10;
   writefln(test[0]);
   x=20;
   writefln(test[0]);
}
Dec 14 2006
prev sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
nazo wrote:
 Expressions! Expressions!  (/ ~.)/
 
 I think that the exchange of parameters of alias is necessary from:
   alias (x*2) exp;
 to:
   alias exp=x*2;

I'm all for that. Changing the order I mean, not necessarily aliases for expressions. Typedef too. They're all just saying symbol=value (where 'value' is a type). But probably it will never change. Alias is too closely connected to typedef, and typedef is too closely connected to C/C++ for Walter to change its syntax. End result: neither will change.
 And I need alias arguments as syntax sugar like:
   alias(alias i) exp=i*2;
 same as:
   template exp(alias i){
     alias exp=i*2;
   }

Hmm, yeh not sure about that. Have to get everyone to swallow the expression alias idea first, which will be tough because they've all been brainwashed into thinking that #define is the 8th deadly sin. :-P --bb
Dec 14 2006
next sibling parent "John Reimer" <terminal.node gmail.com> writes:
On Thu, 14 Dec 2006 12:57:11 -0800, Bill Baxter <wbaxter gmail.com> wrot=
e:

 And I need alias arguments as syntax sugar like:
   alias(alias i) exp=3Di*2;
 same as:
   template exp(alias i){
     alias exp=3Di*2;
   }

Hmm, yeh not sure about that. Have to get everyone to swallow the =

 expression alias idea first, which will be tough because they've all  =

 been brainwashed into thinking that #define is the 8th deadly sin.  :-=

 --bb

8th deadly sin? No..no..no... I'm sure you meant 1st deadly sin! ;D -JJR
Dec 14 2006
prev sibling next sibling parent reply nazo <lovesyao gmail.com> writes:
Bill Baxter wrote:
 nazo wrote:
 Expressions! Expressions!  (/ ~.)/

 I think that the exchange of parameters of alias is necessary from:
   alias (x*2) exp;
 to:
   alias exp=x*2;

I'm all for that. Changing the order I mean, not necessarily aliases for expressions. Typedef too. They're all just saying symbol=value (where 'value' is a type). But probably it will never change. Alias is too closely connected to typedef, and typedef is too closely connected to C/C++ for Walter to change its syntax. End result: neither will change.

alias[] funcs=[unyu,unyu,unyu]; foreach(f;funcs)f();
 And I need alias arguments as syntax sugar like:
   alias(alias i) exp=i*2;
 same as:
   template exp(alias i){
     alias exp=i*2;
   }

Hmm, yeh not sure about that.

current: template f(alias i){ const int f=i*10; } suggestion of syntax sugar: const int f(alias i)=i*10;
 Have to get everyone to swallow the 
 expression alias idea first, which will be tough because they've all 
 been brainwashed into thinking that #define is the 8th deadly sin.  :-P

bad-knowhow!
Dec 14 2006
next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
nazo wrote:
 suggestion of syntax sugar:
   const int f(alias i)=i*10;

Makes me think of my hypothetical Boar language... # // Boar example # module #Math; # function Float sqr ($n) = $n * $n; # function Float cube ($n) = #Math:sqr($n) * $n; Therefore, naturally, I'm not against it. :) -- Chris Nicholson-Sauls
Dec 14 2006
prev sibling parent nazo <lovesyao gmail.com> writes:
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Here is my patch for variable template 'without' alias and typedef.

Test Code:
const int test(int x) = x*2;

void main(){
   static assert(test!(5)==10);
}

#sorry for my poor English.
Dec 14 2006
prev sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Bill Baxter wrote:
 nazo wrote:
 Expressions! Expressions!  (/ ~.)/

 I think that the exchange of parameters of alias is necessary from:
   alias (x*2) exp;
 to:
   alias exp=x*2;

I'm all for that. Changing the order I mean, not necessarily aliases for expressions. Typedef too. They're all just saying symbol=value (where 'value' is a type). But probably it will never change. Alias is too closely connected to typedef, and typedef is too closely connected to C/C++ for Walter to change its syntax. End result: neither will change.
 And I need alias arguments as syntax sugar like:
   alias(alias i) exp=i*2;
 same as:
   template exp(alias i){
     alias exp=i*2;
   }

Hmm, yeh not sure about that. Have to get everyone to swallow the expression alias idea first, which will be tough because they've all been brainwashed into thinking that #define is the 8th deadly sin. :-P --bb

Actually its the 9th deadly sin. The 8th would be copy constructors. That said, i'm actually intrigued by the idea of a expression aliases. I can think of ways they might well be useful -- and I think changing the syntax to "'alias' ident '=' expr ';'" for this particular case wouldn't be too bad either. (If nothing else it would make it perfeclty clear to a parser that this is an expression-alias rather than a symbol-alias.) -- Chris Nicholson-Sauls
Dec 14 2006
prev sibling next sibling parent reply Alexander Panek <a.panek brainsware.org> writes:
Xinok wrote:
 In C++, you can define a constant by using a preprocessor:
 #define INT 30
 
 In D, the standard is to use 'const':
 const int INT = 30;
 
 The problem with the const keyword is it doesn't guarantee the expression will
 be constant.
 const int* PTR = new int; // This technically isn't a constant, the compiler
 just doesn't allow you to modify it's value.

Technically, you can change a constant value in C++, too, if you want. Just get the address and write a little inline assembler to mov x, y something else there. I can't imagine what'd hold me off from that. If you really are so afraid constant values could be changed during runtime, then wright an immutable class, that does for you what you think you need more than D's const.
 
 Another solution is to use enumerators, but they don't aloow any type other
 than int:
 enum { val = 30 } // OK
 enum { str = "Hello" } // Error
 

enum : uint { } // Yay, we've got uint as enum! enum : char { } // Yay, char too! (this works.) The only thing that does not work is an array. Apart from that, you can use any (basic?) type.
 
 So I was thinking, why not give this job to aliases? Aliases must be constant,
 you can use any type with them, and they're easy to write.
 alias 30 VAL;
 alias "Hello" STR;
 alias 31.5 DEC;
 

This is neither type-safe nor anyhow what alias is meant to be.
 Expressions can simply be put within parenthesis:
 alias (15 * 99) EXP;

Same goes here. Sorry, if I sound a bit harsh, but I really dislike preprocessors and is really great /without/ preprocessors. I don't see any need for this. You got version() statements, static if's and what not. It's way cleaner and simpler to read, why insert something in the language just half a month before the language goes 1.0, that is *actually* deprecated and (IIRC) has been discussed in other forms already a few times? Really. No need for that. D is not C++. Kind Regards, Alex
Dec 14 2006
parent reply janderson <askme me.com> writes:
Alexander Panek wrote:
 Xinok wrote:
 
 Technically, you can change a constant value in C++, too, if you want. 
 Just get the address and write a little inline assembler to mov x, y 
 something else there. I can't imagine what'd hold me off from that.

Actually that would be very difficult to make work, with optimisation. You'd have to find and replace every position the const was used (including ones that have been combined with other constants and optimizations) and replace them.
Dec 15 2006
parent Alexander Panek <a.panek brainsware.org> writes:
janderson wrote:
 Alexander Panek wrote:
 Xinok wrote:

 Technically, you can change a constant value in C++, too, if you want. 
 Just get the address and write a little inline assembler to mov x, y 
 something else there. I can't imagine what'd hold me off from that.

Actually that would be very difficult to make work, with optimisation. You'd have to find and replace every position the const was used (including ones that have been combined with other constants and optimizations) and replace them.

This depends on how you used const. const uint x = 1; // this is your case, the variable is just set in and has no unique memory address class X { const uint x; this ( ) { this.x = 0; // here, x has an address and const is meant to be a write-once variable, not a constant value as above. } } Alex
Dec 16 2006
prev sibling next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the expression will
 be constant.

It doesn't? How can you modify a const var then? (in D)
Dec 14 2006
next sibling parent reply Alexander Panek <a.panek brainsware.org> writes:
Lutger wrote:
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the 
 expression will
 be constant.

It doesn't? How can you modify a const var then? (in D)

You can modify const variables that are not set directly at declaration (write-once constants) just by getting their address and modifying them through another variable/pointer.
Dec 14 2006
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Alexander Panek wrote:
 Lutger wrote:
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the 
 expression will
 be constant.

It doesn't? How can you modify a const var then? (in D)

You can modify const variables that are not set directly at declaration (write-once constants) just by getting their address and modifying them through another variable/pointer.

So what!! You can violate class encapsulation using pointers too, in fact you can even mess the v-table.
Dec 14 2006
parent Alexander Panek <a.panek brainsware.org> writes:
Hasan Aljudy wrote:
 
 
 Alexander Panek wrote:
 Lutger wrote:
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the 
 expression will
 be constant.

It doesn't? How can you modify a const var then? (in D)

You can modify const variables that are not set directly at declaration (write-once constants) just by getting their address and modifying them through another variable/pointer.

So what!! You can violate class encapsulation using pointers too, in fact you can even mess the v-table.

Hahaha, yea. I don't get what const would change there, either. X-P
Dec 14 2006
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Alexander Panek wrote:
 Lutger wrote:
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the 
 expression will
 be constant.

It doesn't? How can you modify a const var then? (in D)

You can modify const variables that are not set directly at declaration (write-once constants) just by getting their address and modifying them through another variable/pointer.

Haha yes it works. Is that how it should be or is it a bug or compiler limitation? It looks whacky to me. You can only write a const once in a constructor or so says DMD, thus it seems like this subverts the system in more than one way. I can't imagine that ever being useful.
Dec 14 2006
parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Lutger wrote:
 Alexander Panek wrote:
 Lutger wrote:
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the 
 expression will
 be constant.

It doesn't? How can you modify a const var then? (in D)

You can modify const variables that are not set directly at declaration (write-once constants) just by getting their address and modifying them through another variable/pointer.

Haha yes it works. Is that how it should be or is it a bug or compiler limitation? It looks whacky to me. You can only write a const once in a constructor or so says DMD, thus it seems like this subverts the system in more than one way. I can't imagine that ever being useful.

Why not? It's useful when you work with sane programmers. After all, with pointers and asm, there's no limit to how many things you can mess.
Dec 14 2006
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Hasan Aljudy wrote:
 
 
 Lutger wrote:
 Alexander Panek wrote:
 Lutger wrote:
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the 
 expression will
 be constant.

It doesn't? How can you modify a const var then? (in D)

You can modify const variables that are not set directly at declaration (write-once constants) just by getting their address and modifying them through another variable/pointer.

Haha yes it works. Is that how it should be or is it a bug or compiler limitation? It looks whacky to me. You can only write a const once in a constructor or so says DMD, thus it seems like this subverts the system in more than one way. I can't imagine that ever being useful.

Why not? It's useful when you work with sane programmers. After all, with pointers and asm, there's no limit to how many things you can mess.

Sure, if you want it you can break the type system. But there are some barriers for pointers, these are still typed. I don't think it is so obscure. If you have a const value type in a class, you must set it in the initializer or the constructor. You also cannot modify it. Fine, but then if you have a getter return a reference to it, suddenly all bets are off. This is not what I'd expect, probably because of a C++ bias I still have somewhere, that I (wrongly) think const is part of the type system?
Dec 14 2006
parent reply Don Clugston <dac nospam.com.au> writes:
Lutger wrote:
 Hasan Aljudy wrote:
 Lutger wrote:
 Alexander Panek wrote:
 Lutger wrote:
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the 
 expression will
 be constant.

It doesn't? How can you modify a const var then? (in D)

You can modify const variables that are not set directly at declaration (write-once constants) just by getting their address and modifying them through another variable/pointer.

Haha yes it works. Is that how it should be or is it a bug or compiler limitation? It looks whacky to me. You can only write a const once in a constructor or so says DMD, thus it seems like this subverts the system in more than one way. I can't imagine that ever being useful.

Why not? It's useful when you work with sane programmers. After all, with pointers and asm, there's no limit to how many things you can mess.

Sure, if you want it you can break the type system. But there are some barriers for pointers, these are still typed. I don't think it is so obscure. If you have a const value type in a class, you must set it in the initializer or the constructor. You also cannot modify it. Fine, but then if you have a getter return a reference to it, suddenly all bets are off. This is not what I'd expect, probably because of a C++ bias I still have somewhere, that I (wrongly) think const is part of the type system?

The confusion comes from the way that D uses const in two ways. const XXX = YYY; really is const, cannot be changed (even in theory), and probably won't appear in the executable at all. This is definitely part of the type system. const XXX; is not const at all (it's a variable!). 'final' might have been a better name. As you mention, the read-only protection seems to be very fragile. It seems a very hard thing to enforce.
Dec 14 2006
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Don Clugston wrote:
 The confusion comes from the way that D uses const in two ways.
 const XXX = YYY;
 really is const, cannot be changed (even in theory), and probably won't 
 appear in the executable at all. This is definitely part of the type 
 system.
 
 const XXX;
 is not const at all (it's a variable!). 'final' might have been a better 
 name. As you mention, the read-only protection seems to be very fragile.
 It seems a very hard thing to enforce.

Thank you for the clarification. This means that the original statement from the OP is not true: "In D, the standard is to use 'const': const int INT = 30; The problem with the const keyword is it doesn't guarantee the expression will be constant." Then the issue with consts (the first type) in structs and const structs must be a bug? I was wrong btw about references to members, it only applies to structs not primitives.
Dec 14 2006
parent Don Clugston <dac nospam.com.au> writes:
Lutger wrote:
 Don Clugston wrote:
 The confusion comes from the way that D uses const in two ways.
 const XXX = YYY;
 really is const, cannot be changed (even in theory), and probably 
 won't appear in the executable at all. This is definitely part of the 
 type system.

 const XXX;
 is not const at all (it's a variable!). 'final' might have been a 
 better name. As you mention, the read-only protection seems to be very 
 fragile.
 It seems a very hard thing to enforce.

Thank you for the clarification. This means that the original statement from the OP is not true: "In D, the standard is to use 'const': const int INT = 30; The problem with the const keyword is it doesn't guarantee the expression will be constant."

You are correct. The OP statement is untrue. It's an important distinction -- if it's really a constant, you can use it inside a 'static if'. And you're not allowed to take the address of it.
 Then the issue with consts (the first type) in structs and const structs 
 must be a bug?

I think so. There are a few quirks with array literals and apparently consts as well -- they look like compile-time constants, but AFAIK they are currently implemented as "read-only" variables.
 I was wrong btw about references to members, it only applies to structs 
 not primitives.

Dec 14 2006
prev sibling parent reply "Tomas Lindquist Olsen" <tomas famolsen.dk> writes:
Lutger wrote:

 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the
 expression will be constant.

It doesn't? How can you modify a const var then? (in D)

This actually feels more like a bug, but here's an example: module noconst; import std.stdio; struct S { float f; } const S s = {3.1415}; void main() { writefln(s.f); s.f = 666; writefln(s.f); } (DMD.177)
Dec 14 2006
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Tomas Lindquist Olsen wrote:
 Lutger wrote:
 
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the
 expression will be constant.


This actually feels more like a bug, but here's an example: module noconst; import std.stdio; struct S { float f; } const S s = {3.1415}; void main() { writefln(s.f); s.f = 666; writefln(s.f); } (DMD.177)

Huh yes, const doesn't work at all for structs. This also compiles: struct S { const int i; } void main() { S s; s.i = 10; s.i = 666; }
Dec 14 2006
prev sibling parent Sean Kelly <sean f4.ca> writes:
Tomas Lindquist Olsen wrote:
 Lutger wrote:
 
 Xinok wrote:
 The problem with the const keyword is it doesn't guarantee the
 expression will be constant.


This actually feels more like a bug, but here's an example: module noconst; import std.stdio; struct S { float f; } const S s = {3.1415}; void main() { writefln(s.f); s.f = 666; writefln(s.f); } (DMD.177)

On Windows, DMD doesn't put constants into ROM. I'm not entirely sure why, but I suspect it may be that the OS doesn't support the idea? Sean
Dec 14 2006
prev sibling parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
I think you're proposing a preprocessor .. something that D deliberately 
dropped from C/C++

Xinok wrote:
 In C++, you can define a constant by using a preprocessor:
 #define INT 30
 
 In D, the standard is to use 'const':
 const int INT = 30;
 
 The problem with the const keyword is it doesn't guarantee the expression will
 be constant.
 const int* PTR = new int; // This technically isn't a constant, the compiler
 just doesn't allow you to modify it's value.
 
 Another solution is to use enumerators, but they don't aloow any type other
 than int:
 enum { val = 30 } // OK
 enum { str = "Hello" } // Error
 
 
 So I was thinking, why not give this job to aliases? Aliases must be constant,
 you can use any type with them, and they're easy to write.
 alias 30 VAL;
 alias "Hello" STR;
 alias 31.5 DEC;
 
 Expressions can simply be put within parenthesis:
 alias (15 * 99) EXP;

Dec 14 2006