www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Manifest constants - why not 'alias' ?

reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Alias makes a lot more sense to me than enum.

alias x = 5;
alias float[] y = [1.0,2.0,3.0];

Conceptually, the variable becomes an alias for the literal.

Enum is short for 'unumeration'.  But manifest constants aren't 
enumerating anything.  It makes no sense.

--bb
Dec 06 2007
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Enum is short for 'unumeration'.  But manifest constants aren't 
 enumerating anything.  It makes no sense.

Because we already use enums to declare constant values. enum { x = 3 }
Dec 06 2007
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 Enum is short for 'unumeration'.  But manifest constants aren't 
 enumerating anything.  It makes no sense.

Because we already use enums to declare constant values. enum { x = 3 }

Will enum be able to work as a modifier as in: enum { int x = 3; auto y = "hello"; } ...? Also, unrelated, will there be a way to declare a class variable that is constant after construction (it is assigned once in the constructor, then doesn't change)?
Dec 06 2007
parent Walter Bright <newshound1 digitalmars.com> writes:
Robert Fraser wrote:
 Walter Bright wrote:
 Bill Baxter wrote:
 Enum is short for 'unumeration'.  But manifest constants aren't 
 enumerating anything.  It makes no sense.

Because we already use enums to declare constant values. enum { x = 3 }

Will enum be able to work as a modifier as in: enum { int x = 3; auto y = "hello"; } ...?

I seriously doubt it <g>.
 Also, unrelated, will there be a way to declare a class variable that is 
 constant after construction (it is assigned once in the constructor, 
 then doesn't change)?

Yes, just don't supply an initializer for it: class C { const int x; this() { x = 3; // ok } void foo() { x = 3; // error, x is const } }
Dec 06 2007
prev sibling next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 Enum is short for 'unumeration'.  But manifest constants aren't 
 enumerating anything.  It makes no sense.

Because we already use enums to declare constant values. enum { x = 3 }

That is a trick to declare a constant. You can also do this: class Constants { static int x = 3; } And then you refer it as Constants.x So a possible syntax for defining constants could be class static int x = 3;
Dec 06 2007
prev sibling next sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Walter Bright, el  6 de diciembre a las 16:51 me escribiste:
 Bill Baxter wrote:
Enum is short for 'unumeration'.  But manifest constants aren't enumerating
anything.  It 
makes no sense.

Because we already use enums to declare constant values. enum { x = 3 }

That's the worst reason ever! There are so many things we already use that sucks... As has been already said, we use enum to declare constants because is the only (ugly) way. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- MATAN AL PERRO: DICEN QUE ESTABA POSEIDO POR EL DEMONIO... -- Crónica TV
Dec 07 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
 On 12/7/07, Leandro Lucarella <llucax gmail.com> wrote:
 That's the worst reason ever! There are so many things we already use that
 sucks...

Yep, I agree with everyone. Especially with the above comment. I will certainly /stop/ writing enum { x=3 } if a more intuitive way comes along. So there you have it, Walter: Unanimous support on this newsgroup (...is that unprecedented?...) for NOT using enum as a storage class to define compile-time constants. We all seem to be cool with the concept, just not with the word "enum". My fave is "final", but I'd be happy with any of the other alternatives that have been suggested so far.

Agreed. I really don't see why you wouldn't use final. It seems perfect. Walter just declared there would be no more final, so it's suddenly a keyword without much to do. It's previous meaning as a head const storage class puts it in the right syntax category already. So what's wrong with it? --bb
Dec 07 2007
parent Robert Fraser <fraserofthenight gmail.com> writes:
Bill Baxter wrote:
 Agreed.  I really don't see why you wouldn't use final.  It seems 
 perfect.  Walter just declared there would be no more final, so it's 
 suddenly a keyword without much to do.  It's previous meaning as a head 
 const storage class puts it in the right syntax category already.  So 
 what's wrong with it?
 
 --bb

class X { final { void foo() { } // Method cannot be overriden in a subclass int x = 5; // Manifest constant } }
Dec 07 2007
prev sibling next sibling parent Christopher Wright <dhasenan gmail.com> writes:
Janice Caron wrote:
 On 12/7/07, Leandro Lucarella <llucax gmail.com> wrote:
 That's the worst reason ever! There are so many things we already use that
 sucks...

Yep, I agree with everyone. Especially with the above comment. I will certainly /stop/ writing enum { x=3 } if a more intuitive way comes along. So there you have it, Walter: Unanimous support on this newsgroup (...is that unprecedented?...) for NOT using enum as a storage class to define compile-time constants.

The objections are not quite unanimous. I don't see a problem with it. I do, however, have a problem with using 'final'. It just doesn't have any indication of being constant in my mind, since I've used Java and been able to assign to final variables time out of mind. Using enum has the benefit that nobody has ever been able to assign to an enum value. Also, enum has the benefit of allowing groupings of constants. Potentially, at least, and certainly if you allow for casts, though that's cheating and ugly.
Dec 07 2007
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Janice Caron wrote:
 On 12/7/07, Leandro Lucarella <llucax gmail.com> wrote:
 That's the worst reason ever! There are so many things we already use that
 sucks...

Yep, I agree with everyone. Especially with the above comment. I will certainly /stop/ writing enum { x=3 } if a more intuitive way comes along.

Why isn't: enum x = 3; more intuitive?
 So there you have it, Walter: Unanimous support on this newsgroup
 (...is that unprecedented?...) for NOT using enum as a storage class
 to define compile-time constants.
 
 We all seem to be cool with the concept, just not with the word
 "enum". My fave is "final", but I'd be happy with any of the other
 alternatives that have been suggested so far.

Let's look at final for a moment. Final is currently a storage class for member functions, as in: final { int foo(); int bar(); } but yet: final x = y; is proposed. This doesn't work too well in the syntax, as we don't have: typedef { int myint; } either, would we really want: final { x = y; } ? I don't think that looks right. alias also has strange syntactical problems already discussed, like does: alias int x = 3; make any intuitive sense? Why does: final int x = 3; make any more intuitive sense than: enum int x = 3; ? And lastly, since anonymous enumerated constants are already just what we need, and the proposed new enum variation is just a syntactic shorthand for an anonymous enum with one member, what is the intuitive argument for when one should use a final and when one should use an enum?
Dec 07 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Walter Bright wrote:
 Janice Caron wrote:
 On 12/7/07, Leandro Lucarella <llucax gmail.com> wrote:
 That's the worst reason ever! There are so many things we already use 
 that
 sucks...

Yep, I agree with everyone. Especially with the above comment. I will certainly /stop/ writing enum { x=3 } if a more intuitive way comes along.

Why isn't: enum x = 3; more intuitive?

Because you're *not* *enumerating* anything. From wikipedia: """ In computer programming, an enumerated type is an abstract data type used to model an attribute that has a specific number of options (or identifiers) such as the suit of a playing card (i.e. a Club, Diamond, Heart or Spade). Using this type allows the program to handle the attribute more efficiently than a string while maintaining the readability of the source code. """
 Let's look at final for a moment. Final is currently a storage class for 
 member functions, as in:
     final
     {
         int foo();
         int bar();
     }
 but yet:
     final x = y;
 is proposed. This doesn't work too well in the syntax, as we don't have:
     typedef
     {
         int myint;
     }
 either, would we really want:
     final
     {
         x = y;
     }

Actually I kind of like that block typedef! Often templated classes start off with a preamble of aliases. It would be nice to put them all in a block. (But it would be easier to read if it could be done with the x = y style, since "int myint" looks like it's declaring an integer variable).
 ? I don't think that looks right. alias also has strange syntactical 
 problems already discussed, like does:
     alias int x = 3;
 make any intuitive sense? 

Sure! It means alias x = cast(int)3; it's an alias for the literal 3 that you're specifying you would like the compiler to treat as an int. But since it acts like a variable you can declare it using a variant of standard variable syntax.
 Why does:
     final int x = 3;
 make any more intuitive sense than:
     enum int x = 3;
 ? 

There are these things called "words". And they have "meanings"... enum: (short for "enumeration", the noun form of "enumerate") "to specify one after another : list" final: "not to be altered or undone <all sales are final>" (definitions courtesy m-w.com)
 And lastly, since anonymous enumerated constants are already just what 
 we need, 

Enumerated constants are *not* what we need. We need manifest constants. We're not enumerating anything! We're just trying to declare shorthand name for a constant value.
 and the proposed new enum variation is just a syntactic 
 shorthand for an anonymous enum with one member, 

That's the only thing using 'enum' has going for it.
 what is the intuitive 
 argument for when one should use a final and when one should use an enum?

The description in wikipedia is decent: http://en.wikipedia.org/wiki/Enumerated_type C's enumerated types already bastardized the concept a bit by allowing specific values to be assigned. D goes further in some ways by allowing you to specify a type for the enum as well. And this new proposal is like the nail through the heart of any vestigial meaning remaining in the word 'enum', either mathematical or layman's. --bb
Dec 07 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Bill Baxter wrote:
 Walter Bright wrote:

 and the proposed new enum variation is just a syntactic shorthand for 
 an anonymous enum with one member, 


The main reason for enum to exist and to be called "enum" in the first place is because of its behavior of automatically assigning numeric values to a list of symbols. The purpose for enums originally in C was to provide symbolic sets. Like: enum { DIAMOND, HEART, CLUB, SPADE }; It doesn't really matter what the values are. And in fact in some languages like OCaml I think you can't even ask what the value of DIAMOND is. It's just a symbol that compares equal with DIAMOND and unequal with HEART, CLUB, and SPADE. And I seem to recall they are rather proud of that fact that they have "real" enumerated types. Rather than further watering down the meaning of "enum" I think it would make more sense to scale it back to being a simple automatically numbered list of symbols. And let alias take all the other uses. // manifest constant (literal/constant alias) alias int Foo = 10; // Group of manifest constants (literal/constant alias) alias { int Foo = 10; int Bar = 20; } // Alias for type alias float_t = float; // Alias for type (nod to C syntax for people converting code) alias float float_t; // Group of type aliases alias { float_t = float; int_t = int; vector_t = vec!(int); } // module aliases alias math = std.math; // module aliases (legacy syntax. keep or phase out slowly) alias std.math math; // Mix n match! alias { float_t = float; float PI = 3.14159; math = std.math; } They all have the common meaning of "let X be a new name for Y". Actually it becomes a lot like a safe version #define. And then you could leave enums for the things where you really do want the automatic numbering behavior that it's named after. enum Suit { HEART,DIAMOND,SPADE,CLUB } --bb
Dec 07 2007
prev sibling next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/7/07, Leandro Lucarella <llucax gmail.com> wrote:
 That's the worst reason ever! There are so many things we already use that
 sucks...

Yep, I agree with everyone. Especially with the above comment. I will certainly /stop/ writing enum { x=3 } if a more intuitive way comes along. So there you have it, Walter: Unanimous support on this newsgroup (...is that unprecedented?...) for NOT using enum as a storage class to define compile-time constants. We all seem to be cool with the concept, just not with the word "enum". My fave is "final", but I'd be happy with any of the other alternatives that have been suggested so far.
Dec 07 2007
prev sibling next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/8/07, Walter Bright <newshound1 digitalmars.com> wrote:
 Why isn't:
         enum x = 3;
 more intuitive?

I didn't say it wasn't intutive. /Anything/ is intuitive, once you get used to it, if the syntax is simple enough, and I can't argue that this isn't simple. I said it was the wrong word. "enum" is short for "enumeration". It should be used for the purpose of enumeration, and nothing more. Honestly, I wish D had /real/ enumerations, so you could do enum Col { red, orange, yellow, green, blue, indigo, violet }; to indiciate that Col was a type defining an ordered sequence of symbols. It has a /first/ element (red), a last element (violet), a successor/precedessor relationship (the successor of yellow is green), and comparison functions whose meaning is "left of" and "right of". Elements would have a toString() function, so that orange.toString == "orange". But what these beasts would NOT have any numerical properties at all. Converting to or from int is just not possible. You know - /proper/ enums! (Of course, that's not going to happen, so this is not a feature request. The current implementation lets me /pretend/ that enums are proper enums, and that's probably good enough). We all love the idea of compile-time constants. They're a /great/ idea. Just, please use the right word to express them. If you don't like "final", not a problem. Others have suggested "alias", "macro", "define" and "let", and any one of those would make me happy.
Dec 08 2007
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/8/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:
 There are these things called "words".  And they have "meanings"...

Yes, that's /exactly/ the point I was making. Well said, Bill.
Dec 08 2007
prev sibling parent reply David Gileadi <foo bar.com> writes:
Bill Baxter wrote:
 Alias makes a lot more sense to me than enum.
 
 alias x = 5;
 alias float[] y = [1.0,2.0,3.0];
 
 Conceptually, the variable becomes an alias for the literal.
 
 Enum is short for 'unumeration'.  But manifest constants aren't 
 enumerating anything.  It makes no sense.
 
 --bb

FWIW, alias makes the most sense to me out of the current crop of suggestions. To me it says that wherever I see the alias, it will be replaced with whatever value the alias is for. That seems to describe manifest constants exactly.
Dec 06 2007
next sibling parent sambeau <please-dont-spam-sambeau mac.com> writes:
David Gileadi Wrote:

 Bill Baxter wrote:
 Alias makes a lot more sense to me than enum.
 
 alias x = 5;
 alias float[] y = [1.0,2.0,3.0];
 
 Conceptually, the variable becomes an alias for the literal.
 
 Enum is short for 'unumeration'.  But manifest constants aren't 
 enumerating anything.  It makes no sense.
 
 --bb

FWIW, alias makes the most sense to me out of the current crop of suggestions. To me it says that wherever I see the alias, it will be replaced with whatever value the alias is for. That seems to describe manifest constants exactly.

This all makes sense as an implementation, but not as a language design. You need to step back and look at the word 'enum' and ask yourself does it make sense? Surely, if you are proposing to change the use of 'enum' in this significant way you should change it's name. Otherwise everyone will be confused. Def, let, constants, defines, ... , etc They all have two advantages 1) they sound like what they do 2) they aren't a reuse of something that already does something I know that many people always go on about how many reserved words a language has and treats it like a badge of honor. But we can't all be Lisp. I would rather use keywords that make sense than reuse the same keyword for more than one distinct use.. static, extrern, const, ..., blah! :-)
Dec 06 2007
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
David Gileadi wrote:
 FWIW, alias makes the most sense to me out of the current crop of 
 suggestions.  To me it says that wherever I see the alias, it will be 
 replaced with whatever value the alias is for.  That seems to describe 
 manifest constants exactly.

Since there's already: alias X Y; it would seem confusing to add: alias Y = X;
Dec 06 2007
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
mandel wrote:
 On Thu, 06 Dec 2007 21:07:18 -0800, Walter Bright wrote:
 
 David Gileadi wrote:
 FWIW, alias makes the most sense to me out of the current crop of
 suggestions.  To me it says that wherever I see the alias, it will be
 replaced with whatever value the alias is for.  That seems to describe
 manifest constants exactly.

alias X Y; it would seem confusing to add: alias Y = X;

I know it was asked before for sure, but could someone point out why not just use: alias Y 42; alias Z "abc"; alias X [1,2,3];

No type safety.
Dec 06 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Robert Fraser wrote:
 mandel wrote:
 On Thu, 06 Dec 2007 21:07:18 -0800, Walter Bright wrote:

 David Gileadi wrote:
 FWIW, alias makes the most sense to me out of the current crop of
 suggestions.  To me it says that wherever I see the alias, it will be
 replaced with whatever value the alias is for.  That seems to describe
 manifest constants exactly.

alias X Y; it would seem confusing to add: alias Y = X;

I know it was asked before for sure, but could someone point out why not just use: alias Y 42; alias Z "abc"; alias X [1,2,3];

No type safety.

And the above is also backwards from current alias syntax. The newly defined thing goes on the right, not the left. --bb
Dec 06 2007
prev sibling parent "Craig Black" <cblack ara.com> writes:
"Walter Bright" <newshound1 digitalmars.com> wrote in message 
news:fjake2$cid$2 digitalmars.com...
 David Gileadi wrote:
 FWIW, alias makes the most sense to me out of the current crop of 
 suggestions.  To me it says that wherever I see the alias, it will be 
 replaced with whatever value the alias is for.  That seems to describe 
 manifest constants exactly.

Since there's already: alias X Y; it would seem confusing to add: alias Y = X;

I would prefer the syntax alias X = Y even for types. To me it's more explicit and consistent with the rest of the language.
Dec 07 2007
prev sibling next sibling parent mandel <oh no.es> writes:
On Thu, 06 Dec 2007 21:07:18 -0800, Walter Bright wrote:

 David Gileadi wrote:
 FWIW, alias makes the most sense to me out of the current crop of
 suggestions.  To me it says that wherever I see the alias, it will be
 replaced with whatever value the alias is for.  That seems to describe
 manifest constants exactly.

Since there's already: alias X Y; it would seem confusing to add: alias Y = X;

I know it was asked before for sure, but could someone point out why not just use: alias Y 42; alias Z "abc"; alias X [1,2,3]; - it points out that it doesn't have a memory address (no '=' assigment) - it will be filled in for X, Y, Z btw.: enum for compile time constants doesn't fit it's main meaning (enumeration), but it's secondary meaning as compile time constants. It's also limited (regarding to strings etc.). I would call it a hack. :P
Dec 06 2007
prev sibling next sibling parent mandel <oh no.es> writes:
On Fri, 07 Dec 2007 15:28:19 +0900, Bill Baxter wrote:

 Robert Fraser wrote:
 alias Y 42;
 alias Z "abc";
 alias X [1,2,3];


And the above is also backwards from current alias syntax. The newly defined thing goes on the right, not the left. --bb

oops, that wasn't intended. :)
Dec 06 2007
prev sibling next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On Dec 7, 2007 2:36 AM, sambeau <please-dont-spam-sambeau mac.com> wrote:
 This all makes sense as an implementation, but not as a language design.
 You need to step back and look at the word 'enum' and ask yourself does it
make sense?

 Surely, if you are proposing to change the use of 'enum' in this significant
way you should change it's name. Otherwise everyone will be confused.

 Def, let, constants, defines,  ... , etc

 They all have two advantages
 1) they sound like what they do
 2) they aren't a reuse of something that already does something

That makes sense. From a purely /conceptual/ point of view, "true" enums shouldn't have any numerical value at all - just a successor/predecessor relationship. That is, one can imagine (in a different language) enum Month { January, February, March, April, May, June, July, August, September, October, November, December }; Month m = Month.February; Month n = m.successor(); if (n > m) { /*...*/ } without ever exposing the implementation, or the internally stored value, which now matters only to the compiler. However... C did not adopt that model. Instead, C mandated that enums be implemented as an int, and C++ copied C. D then copied C/C++, but with the added feature that you get to specify the underlying type. So now we've got what we've got, and either we stick with it (...in which case I see no harm in either (a) allowing underlying types to be non-integer, or (b) treating the braces as optional...), or we rethink and start again. We /could/ rethink and start again. We could define a new reserved word (I'm going to use "meta", just for argument's sake) which means "available at compile time". It could replace all current uses of "const" and "static" for that purpose ("static if", CTFE, etc.). That being done, one could then write meta int x = 3; or just meta x = 3; with type-deduction, to get a compile-time constant, and consistent keyword usage. "enum" could then be retooled to act more like a "true" enum should. Actually, I'd quite like that option. The problem is, it's probably too great a breaking change. If it only broke D2 code, no one would complain, but this would break D1 code as well. So, with that bourne in mind, Walter's solution really isn't bad.
Dec 07 2007
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
Of all the suggestions so far, my favourite is actually the one
suggested by Paul Anderson: final.

    final x = 3;

with type deduction, or

    final int x = 3;

without. When grouped:

    final
    {
        version = 3.1;
        author = "Janice";
    }

in all cases, we are declaring compile-time constants which occupy
zero storage space at runtime - exactly what Walter is suggesting
using "enum" for right now. After all, "final" is already a reserved
word, so it's not like we'd be adding a new one.
Dec 07 2007