www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9065] New: Please consider adding these std.traits

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065

           Summary: Please consider adding these std.traits
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody puremagic.com
        ReportedBy: turkeyman gmail.com



I'm constantly writing static logic code where I have no real idea what I'm
really doing, and when I finally get it working, it's unreadable.
This usually involves lots of careful is()-ing and __traits-ing.

I'd really appreciate these templates added to std.traits:

Tell me if T is a variable; ie, has a value, has an address (not an enum), ...
template isVariable(alias T) { ... }

Tell me if T is a function definition, not just if I can call it. I can easily
find if something is a function pointer/delegate, or a method, or virtual, or
abstract, or various other function related details, but surprisingly, not if T
is just a function definition or not.
template isFunctionDefinition(alias T) { ... }

I want to know if I is an instance of some template T.
template isInstanceOf(alias T, I) { ... }

Perhaps like this: http://dpaste.dzfl.pl/fedac944

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 23 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065


Andrej Mitrovic <andrej.mitrovich gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich gmail.com



09:59:20 PST ---

 template isInstanceOf(alias T, I) { ... }
That one is now in Phobos: http://d.puremagic.com/issues/show_bug.cgi?id=9064 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 template isInstanceOf(alias T, I) { ... }
That one is now in Phobos: http://d.puremagic.com/issues/show_bug.cgi?id=9064
Sweet. Any chance of the other 2? I'd really like to delete all my unreadable fail code asap. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065


David Nadlinger <code klickverbot.at> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |code klickverbot.at



PST ---
For the second point, what about is(T == function)? The is() syntax is not very
popular (rightfully so), but I am not sure if we have a decision to replicate
even its most basic use cases in std.traits yet.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 For the second point, what about is(T == function)? The is() syntax is not very
 popular (rightfully so), but I am not sure if we have a decision to replicate
 even its most basic use cases in std.traits yet.
Does that not test if T is some sort of function pointer? ...actually, that's some sort of special case overloaded meaning of the function keyword in conjunction with 'is' isn't it? I think I remember running into that like, a year ago. I recall being very confused at the time. Will that only pass in function definitions? Will exclude function pointers? The first point is by far the most important, it's the one I really have no idea how to do properly myself. I have templates that kinda work, but seem to break in some cases, and I use it constantly. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




PST ---

 Does that not test if T is some sort of function pointer?
 
 ...actually, that's some sort of special case overloaded meaning of the
 function keyword in conjunction with 'is' isn't it? I think I remember running
 into that like, a year ago. I recall being very confused at the time.
 Will that only pass in function definitions? Will exclude function pointers?
Yes, this is one of the ugliest parts of the is() syntax. You are probably right, the fact alone that "function" has a different meaning here than in the rest of the language probably warrants inclusion of an isFunction() trait… -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065


Jonathan M Davis <jmdavisProg gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jmdavisProg gmx.com



PST ---
is(T == function) actually tests whether T is the type of a function, not
whether it's a function pointer. This stackoverflow question discusses the
differences between is(T == function), isFunctionPointer!T, isDelegate!T, and
isSomeFunction!T:

http://stackoverflow.com/questions/11067972/functions-versus-function-pointers-whats-the-difference



We may want to add more of these to std.traits, but we should probably think
carefully about exactly what we should add, especially because is expressions
do most (all?) of it already, and often fairly cleanly. It's just that they're
complicated enough in general and not understood well enough, that many people
don't have a clue what they can do. It still may be worth adding stuff like
isVariable to std.traits though.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 is(T == function) actually tests whether T is the type of a function, not
 whether it's a function pointer. This stackoverflow question discusses the
 differences between is(T == function), isFunctionPointer!T, isDelegate!T, and
 isSomeFunction!T:
 
 http://stackoverflow.com/questions/11067972/functions-versus-function-pointers-whats-the-difference
Looking at that link, what's with all the typeof(bar) stuff? Do those tempaltes not work by alias? Surely I should be able to say isSomeFunction!bar, not requiring isSomeFunction!(typeof(bar)) ? Using typeof() like that makes generic code harder, because 'bar' could be anything, and if it doesn't have a typeof, then it is a different compile error and I have to produce even more logic prior to eliminate that case. Surely that could be encapsulated?

 
 We may want to add more of these to std.traits, but we should probably think
 carefully about exactly what we should add, especially because is expressions
 do most (all?) of it already, and often fairly cleanly. It's just that they're
 complicated enough in general and not understood well enough, that many people
 don't have a clue what they can do. It still may be worth adding stuff like
 isVariable to std.traits though.
In my experience, code to the effect of isVariable is actually rather non-trivial. It would be very useful. Ideally, written by someone who knows what they're doing ;) (I clearly don't) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





It's interesting to note that in your very first reply you were confused by is(T == function) too. I really think isFunction! should be added. It seems there is significant evidence to support it. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




PST ---
 Looking at that link, what's with all the typeof(bar) stuff? Do those
 tempaltes not work by alias? Surely I should be able to say
 isSomeFunction!bar, not requiring isSomeFunction!(typeof(bar)) ?
std.traits operates on types, so I would not expect isSomeFunction!bar to ever work. You need to pass it a type. That's how everything in that module works. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




PST ---

 std.traits operates on types, so I would not expect isSomeFunction!bar to ever
 work. You need to pass it a type. That's how everything in that module works.
This is definitely not true. Just have a look at isSomeFunction/isCallable resp. their unit tests. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 25 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




Okay, I've worked my templates a little more, consider these:

// test if something is a type
template isType( alias T )
{
    enum isType = is( T );
}
template isType( T )
{
    enum isType = is( T );
}

// test if something is a function
// wrap this up, 'function' is an overloaded term, confusing for newbies
template isFunction( alias T )
{
    enum isFunction = is( typeof( T ) == function );
}
template isFunction( T )
{
    enum isFunction = is( T == function );
}

// test if something is an enum (used by isVariable)
template isEnum( alias T )
{
    template knownAtCompileTime( alias T )
    {
//        enum knownAtCompileTime = is( typeof( { enum e = T; } ) ); //
immutable breaks this check
        enum knownAtCompileTime = !__traits(compiles, ( ref typeof( T ) x ) {}(
T ) ); // hack to see if we can pass it by ref
    }

    enum isEnum = is( typeof( T ) == enum ) || knownAtCompileTime!T;
}
template isEnum( T )
{
    enum isEnum = is( T == enum );
}

// test if something is a variable; has a value, has an address
template isVariable( alias T )
{
    enum isVariable = !is( T ) && is( typeof( T ) )    // if it is not a type,
and does have a type, it starts to look like a variable
        && !isFunction!T                            // reject function
definitions, they can't be assigned to
        && !isEnum!T                                // reject enum's
        && !is( typeof( T ) == void );                // reject modules, which
appear as a variable of type 'void'
}
template isVariable( T )
{
    enum isVariable = false; // types aren't variables
}


This seems to be working for me now (caught a few more edge cases that would
fail on occasion). I'd really like to see all of these in std.traits.
It would be ideal if is() was a rare occurrence, it produces bracket spam, and
most I work with barely understand it past expressions like: is(T == int)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




---

 Okay, I've worked my templates a little more, consider these:
[snip] 1. I would never agree with isFunction. They introduce huge confusion but has no benefit. Blending traits about type and symbol is not a purpose of std.traits. 2. isEnum should be separated to isEnumType and isManifestConstant (with better name). Blending traits is very poor design. And, there is no use case. if you propose an enhancement, you should show one or more use cases in order to claim its usefulness. (I always doubt the reason like "for the newbie". Increase of language newbies is not worth than an increase of the design confusion in the standard library.) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




Turns out this is still incomplete:

isEnum fails in some situations. Using 'compiles' like that is not reliable
with various levels of aliases/templates.
Also, that implementation of isVariable marks getter-properties as if they are
variables, which they are not.

Back to the drawing board...

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 Okay, I've worked my templates a little more, consider these:
[snip] 1. I would never agree with isFunction. They introduce huge confusion but has no benefit. Blending traits about type and symbol is not a purpose of std.traits.
You would never agree with a std.traits to wrap is(x == function)? Why? It confuses everyone. Nobody expects that overload of meaning.
 2. isEnum should be separated to isEnumType and isManifestConstant (with better
 name). Blending traits is very poor design.
I've never heard this term 'manifest constant' before today. Here's a line of code: enum i = 10; I (and I presume any sane person) would say "that's an enum!". I appreciate there is a distinction between an enum type and an enum value, but they are both called enums, and I doubt any non-D-compiler-developer would presume otherwise. I don't care if they are separated, just that the terminology should make sense.
 And, there is no use case. if you propose an enhancement, you should show one
 or more use cases in order to claim its usefulness.
I work in a studio on highly sensitive proprietary code. Isolating examples out of context is often difficult, annoying, and very time consuming. I don't have the time to convince you in this case. However, if there wasn't a use case, rest assured I wouldn't be posting here, and I wouldn't be wasting consecutive days of my time on it. I need to know these things, D doesn't provide this information; it should. Perhaps this will help: foreach(m; __traits(allMembers, something)) { // What on earth is m? // I think think you can argue this is unconventional code. // I need to know all sorts of things about m in this context, and I have absolutely no prior information. // 'is' traits shouldn't make me jump through bunches of hoops to gather information. }
 (I always doubt the reason like "for the newbie". Increase of language newbies
 is not worth than an increase of the design confusion in the standard library.)
Confusion? Surely you mean simplification? Having 'function' mean 2 to different things in 2 contexts is confusing. Having enum mean 2 different things in almost precisely the same context is confusing. std.traits is meant to simplify my code and save me time. In my experience to date, it's severely lacking. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 Turns out this is still incomplete:
 
 isEnum fails in some situations. Using 'compiles' like that is not reliable
 with various levels of aliases/templates.
 Also, that implementation of isVariable marks getter-properties as if they are
 variables, which they are not.
 
 Back to the drawing board...
I've become convinced I also need to add template isProperty(T) { ... } I can't find any sensible way to do this, and I'm also blocked without it. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065


Jacob Carlborg <doob me.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |doob me.com





 Perhaps this will help:
 
 foreach(m; __traits(allMembers, something))
 {
   // What on earth is m?
   // I think think you can argue this is unconventional code.
   // I need to know all sorts of things about m in this context, and I have
 absolutely no prior information.
   // 'is' traits shouldn't make me jump through bunches of hoops to gather
 information.
 }
I agree with you in general but what's wrong with that example? Sure, the double underscore prefix doesn't look that nice but except from that. What would the alternative be? Something like this: foreach (m; allMembers!(somethnig)) { // What on earth is m? } What's better with that code? The "allMembers" trait is clearly documented here: http://dlang.org/traits.html#allMembers "m" would be a string, since __traits(allMembers, something) returns a tuple of strings. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 
 Perhaps this will help:
 
 foreach(m; __traits(allMembers, something))
 {
   // What on earth is m?
   // I think think you can argue this is unconventional code.
   // I need to know all sorts of things about m in this context, and I have
 absolutely no prior information.
   // 'is' traits shouldn't make me jump through bunches of hoops to gather
 information.
 }
I agree with you in general but what's wrong with that example? Sure, the double underscore prefix doesn't look that nice but except from that. What would the alternative be? Something like this: foreach (m; allMembers!(somethnig)) { // What on earth is m? } What's better with that code? The "allMembers" trait is clearly documented here: http://dlang.org/traits.html#allMembers "m" would be a string, since __traits(allMembers, something) returns a tuple of strings.
*sigh* Sorry, I take no issue with allMembers. My point has nothing to do with allMembers except that it's a common source of symbols that you have no idea what they are. ** "what on earth is mixin(m)?" If you don't know what something is you need to query details about it, and with all the traits as britle and scarce as they are, chances are that leads to many compile errors and consequently rubbish code scattered to protect it against such errors, when rather, such 'is' traits should just produce 'false' instead of compile errors. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




PST ---

 Here's a line of code:
   enum i = 10;
 
 I (and I presume any sane person) would say "that's an enum!".
 I appreciate there is a distinction between an enum type and an enum value, but
 they are both called enums, and I doubt any non-D-compiler-developer would
 presume otherwise.
 
 I don't care if they are separated, just that the terminology should make
 sense.
Yes, but the correct answer to this is to not overload the word "enum" with two different meanings. Unfortunately, this ship has long sailed, but this still doesn't mean that we should repeat this mistake in the standard library, further adding confusion. If you don't like the term manifest constant, maybe isEnumConstant/isEnumType? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 Here's a line of code:
   enum i = 10;
 
 I (and I presume any sane person) would say "that's an enum!".
 I appreciate there is a distinction between an enum type and an enum value, but
 they are both called enums, and I doubt any non-D-compiler-developer would
 presume otherwise.
 
 I don't care if they are separated, just that the terminology should make
 sense.
Yes, but the correct answer to this is to not overload the word "enum" with two different meanings. Unfortunately, this ship has long sailed, but this still doesn't mean that we should repeat this mistake in the standard library, further adding confusion. If you don't like the term manifest constant, maybe isEnumConstant/isEnumType?
Sure, just as long as something useful is added to std.traits. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




---


OK. I understood that Manu says. And my yesterday comment was completely wrong. Sorry for my misunderstanding. Certainly, isFunction is an important template which lacks in std.traits. Existing other function traits, isSomeFunction, isCallble, FunctionTypeOf, return true even if given function pointer or delegate. I can agree with the behavior is sometimes obstacle.
 Blending traits about type and symbol is not a purpose of std.traits.
And more, mixing symbol and type is *a design* of std.traits. I had misunderstood at the point. isSomeFunction is an example. /** Detect whether >>symbol or type<< $(D T) is a function, a function pointer or a delegate. */ template isSomeFunction(T...) { ... } I challenged implementing proposed template isVariable. Is this what you want? https://gist.github.com/4152297 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065







OK. I understood that Manu says. And my yesterday comment was completely wrong. Sorry for my misunderstanding. Certainly, isFunction is an important template which lacks in std.traits. Existing other function traits, isSomeFunction, isCallble, FunctionTypeOf, return true even if given function pointer or delegate. I can agree with the behavior is sometimes obstacle.
 Blending traits about type and symbol is not a purpose of std.traits.
And more, mixing symbol and type is *a design* of std.traits. I had misunderstood at the point. isSomeFunction is an example. /** Detect whether >>symbol or type<< $(D T) is a function, a function pointer or a delegate. */ template isSomeFunction(T...) { ... } I challenged implementing proposed template isVariable. Is this what you want? https://gist.github.com/4152297
It looks good, although I can't test it now. Does isVariable deal with properties (which I would say are NOT variables). And how about an isProperty? That's really hard to detect... I'm not sold on the term isManifestConstant, I'm sure no non-compiler developer would have ever heard that term before. I've never seen it in any docs before, and they're declared with 'enum', that's what most people will call it. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




PST ---
 I'm not sold on the term isManifestConstant, I'm sure no non-compiler 
 developer would have ever heard that term before. I've never seen it in any 
 docs before, and they're declared with 'enum', that's what most people will 
 call it.
I don't know if isManifestConstant is the best name, but it's the official term, and I'm sure that a large portion of the regular newsgroup goers know what it is, not just the compiler devs. I don't know how many outside that group would know it however. Still, given that it's the official name, and that we don't really _have_ another name, I think that I'd still be in favor of isManifestConstant. And if we have isManifestConstant and isEnumType and no isEnum, then we avoid all of the confusion surrounding what exactly an enum is. And it's not like it will be hard for the docs to explain the terms. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




---


 I challenged implementing proposed template isVariable. Is this what you want?
 
 https://gist.github.com/4152297
It looks good, although I can't test it now. Does isVariable deal with properties (which I would say are NOT variables). And how about an isProperty? That's really hard to detect...
Added isPropertyFunction (isProperty is a bit ambiguous name to me). I think it's a trait derived from isFunction.
 I'm not sold on the term isManifestConstant, I'm sure no non-compiler developer
 would have ever heard that term before. I've never seen it in any docs before,
 and they're declared with 'enum', that's what most people will call it.
http://dlang.org/features2.html
 Extended enums to allow declaration of manifest constants.
http://dlang.org/enum.html
 Manifest Constants
  If there is only one member of an anonymous enum, the { } can be omitted:
  [snip]
  Such declarations are not lvalues, meaning their address cannot be taken.
-- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 I'm not sold on the term isManifestConstant, I'm sure no non-compiler 
 developer would have ever heard that term before. I've never seen it in any 
 docs before, and they're declared with 'enum', that's what most people will 
 call it.
I don't know if isManifestConstant is the best name, but it's the official term, and I'm sure that a large portion of the regular newsgroup goers know what it is, not just the compiler devs. I don't know how many outside that group would know it however. Still, given that it's the official name, and that we don't really _have_ another name, I think that I'd still be in favor of isManifestConstant. And if we have isManifestConstant and isEnumType and no isEnum, then we avoid all of the confusion surrounding what exactly an enum is. And it's not like it will be hard for the docs to explain the terms.
There is another name, it's called an 'enum', as clearly stated by the syntax: enum x = 10; Using any term other than that seems crazy by my measure. The user base aren't compiler developers. I don't even know what manifest means. I don't think the distinction isEnumType, isEnumValue is at all confusing, in fact, the function names alone document the important detail that there IS a distinction, and what it is.


 I challenged implementing proposed template isVariable. Is this what you want?
 
 https://gist.github.com/4152297
It looks good, although I can't test it now. Does isVariable deal with properties (which I would say are NOT variables). And how about an isProperty? That's really hard to detect...
Added isPropertyFunction (isProperty is a bit ambiguous name to me). I think it's a trait derived from isFunction.
This highlights another conflict in terminology, currently a property is NOT recognised as a function (at least in my crappy tests). I really think isFunction!someProperty should be true. It's a function, exactly like any other, I can take pointers/delegates of it, it just has a particular usage semantic. Effectively a subset, not a different concept. So I suggest isFunction! should give true for a property function definition.
 I'm not sold on the term isManifestConstant, I'm sure no non-compiler developer
 would have ever heard that term before. I've never seen it in any docs before,
 and they're declared with 'enum', that's what most people will call it.
http://dlang.org/features2.html
 Extended enums to allow declaration of manifest constants.
This clearly implies that 'manifest constant' is in fact some kind of enum.
 http://dlang.org/enum.html
 Manifest Constants
  If there is only one member of an anonymous enum, the { } can be omitted:
  [snip]
  Such declarations are not lvalues, meaning their address cannot be taken.
Again, referring to 'anonymous enum', it's not distancing its self from the enum terminology. ... I just asked 2 other programmers in the room what enum x = 10; is, they said it's an enum, not a manifest constant ;) None of them could tell me what a manifest constant it, or that they'd ever heard of such a thing before. But I don't actually care at the end of the day, I'm just trying to give a voice of reason. What the compiler calls stuff internally has no bearing on what users of the language will call things. The user facing library should endeavour to match the terminology used by the users IMO. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 This highlights another conflict in terminology, currently a property is NOT
 recognised as a function (at least in my crappy tests). I really think
 isFunction!someProperty should be true. It's a function, exactly like any
 other, I can take pointers/delegates of it, it just has a particular usage
 semantic. Effectively a subset, not a different concept.
 
 So I suggest isFunction! should give true for a property function definition.
Sorry! I just saw your unit test asserts isFunction! is true for property functions. I didn't see that behaviour with is(X==function) in my tests. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




04:14:28 PST ---

 What the compiler calls stuff internally has no bearing on
 what users of the language will call things.
It's not an internal thing, that declaration is not an enum declaration, period. enum is used as a keyword for more than one thing, which is bad, but it's too late to change it now. We shouldn't name things in Phobos based on what people might think is right or looks right, but based on what the things really are. It's a shame we don't have a 'manifest' keyword of some sort, it would help avoid confusion. I guess 'enum' was used to cut back on having too many keywords in the language. Anyway it's documented behavior, see "manifest constants" here (it's at the bottom): http://dlang.org/enum.html -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




04:15:48 PST ---

 Anyway it's documented behavior, see "manifest constants" here (it's at the
 bottom): http://dlang.org/enum.html
Actually it's poorly documented, it speaks about "anon" enums but it shouldn't really mention them at all imo. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 It's a shame we don't have a 'manifest' keyword of some sort, it would help
 avoid confusion. I guess 'enum' was used to cut back on having too many
 keywords in the language.
Isn't the whole problem that the compiler and/or linker isn't capable of stripping out symbols that are only used at compile time. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 What the compiler calls stuff internally has no bearing on
 what users of the language will call things.
It's not an internal thing, that declaration is not an enum declaration, period. enum is used as a keyword for more than one thing, which is bad, but it's too late to change it now. We shouldn't name things in Phobos based on what people might think is right or looks right, but based on what the things really are.
I couldn't disagree more. Firstly, what it is clearly documented as, is being some subset of enum. That's what it 'really is'. More importantly, if I look at the top of std.traits for something I presume to be called isEnum, and I see isEnumValue, I'll realise that's actually what I'm looking for immediately, use it, and save myself time. If I see something called isEnum, and it doesn't seem to work because it only reports true for enum TYPES (not values), then I'll declare it broken and report a bug. If I scan through everything in std.traits, and find nothing that looks like what I want, I'll get frustrated the thing I need is missing. If I see isManifestConstant, there is _NO WAY_ I would have even read what that is, it's clearly not what I'm looking for, I'm trying to identify if my thing is an enum...
 It's a shame we don't have a 'manifest' keyword of some sort, it would help
 avoid confusion. I guess 'enum' was used to cut back on having too many
 keywords in the language.
I honestly don't even know what manifest means. The terminology used in the syntax and the documentation is correct; it's a kind of enum.
 Anyway it's documented behavior, see "manifest constants" here (it's at the
 bottom): http://dlang.org/enum.html
And every place it appears, it is clearly defined as being some subset of enum. Again, if I go looking for isEnum, and find a suite of more specific enum related traits (isEnumType, isEnumValue), I can easily conclude which is the one I'm looking for. If the name is completely unrelated and uses terminology most programmers have never heard before, they'll never spot it. As a side point, what do you call X in: enum E { X = 10 } ? Consider: enum E { X = 10 } enum Y = 10; E.X and Y are both identical as far as I can tell. I would presume: isEnumType!E == true, and isEnumValue!(E.X) == isEnumValue!Y == true. You can tweak the names, but I think traits to that effect are a) useful, b) what (I presume) most typical users will expect. E.X and Y are identical. I think this specialised term 'manifest constant' that only applies to Y can only result in confusion. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 
 It's a shame we don't have a 'manifest' keyword of some sort, it would help
 avoid confusion. I guess 'enum' was used to cut back on having too many
 keywords in the language.
Isn't the whole problem that the compiler and/or linker isn't capable of stripping out symbols that are only used at compile time.
It's also one of the things that D got absolutely right! I never questioned this design for a moment, it makes perfect sense to me, but as of yesterday my concept of what an enum is has been thrown up in the air for absolutely no good reason other than terminology used by the D developers. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 https://gist.github.com/4152297
I am seeing a few error cases: enum j { k = 10 } pragma(msg, isFunction!(j.k)); pragma(msg, isManifestConstant!(j.k)); pragma(msg, isPropertyFunction!(j.k)); pragma(msg, isVariable!(j.k)); These all throw errors. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




06:25:56 PST ---

 As a side point, what do you call X in: enum E { X = 10 } ?
 
 Consider:
  enum E { X = 10 }
  enum Y = 10;
 
 E.X and Y are both identical as far as I can tell.
Run typeid() on them.
 And every place it appears, it is clearly defined as being some subset of enum.
Well it wouldn't be the first time the docs lie. :) "enum Y = 10;" is a special case which the compiler checks for and then parses this as a manifest constant, it does not parse it as an enum. "Y" is not an enum value of any sort, Y is a VarDeclaration with storage class STCmanifest. Here: enum E { X = 10 } X is an EnumMember. Just to make this clear, these two are different: enum { X = 10 } enum Y = 10; X is an enum value, whereas Y is a manifest constant and is not associated with enums at all in any way. The issue here is that the "enum" keyword can be a lie. It can mean two things depending on the declaration. It also seems that internally the idea of a manifest keyword was thought about, there's a bunch of commented out lines like so: //case TOKmanifest: stc = STCmanifest; goto Lstc; I wonder who put that in and why it wasn't used.. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 As a side point, what do you call X in: enum E { X = 10 } ?
 
 Consider:
  enum E { X = 10 }
  enum Y = 10;
 
 E.X and Y are both identical as far as I can tell.
Run typeid() on them.
 And every place it appears, it is clearly defined as being some subset of enum.
Well it wouldn't be the first time the docs lie. :) "enum Y = 10;" is a special case which the compiler checks for and then parses this as a manifest constant, it does not parse it as an enum. "Y" is not an enum value of any sort, Y is a VarDeclaration with storage class STCmanifest. Here: enum E { X = 10 } X is an EnumMember. Just to make this clear, these two are different: enum { X = 10 } enum Y = 10; X is an enum value, whereas Y is a manifest constant and is not associated with enums at all in any way.
That's not really how the doc describes it: "If there is only one member of an anonymous enum, the { } can be omitted:" Either way, it's a perfectly reasonably way to visualise it as a user. As I said before, I couldn't care less about internal compiler terminology, it looks like an anonymous enum value, and the doc even says it's an anonymous enum value. It must be so. The doc is correct as far as I'm concerned, it makes perfect sense, the language shouldn't be defined by implementation details of DMD.
 The issue here is that the "enum" keyword can be a lie. It can mean two things
 depending on the declaration.
 
 It also seems that internally the idea of a manifest keyword was thought about,
 there's a bunch of commented out lines like so:
 //case TOKmanifest:   stc = STCmanifest;     goto Lstc;
 
 I wonder who put that in and why it wasn't used..
I'll bet it was realised during implementation that it is actually syntactic sugar for an anonymous enum, and the enum keyword was completely appropriate :) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




 Kenji:

I'm getting an error when using your new isFunction, here's the case:

struct S
{
    static string func(alias Class)()
    {
        foreach(m; __traits(allMembers, Class))
        {
            pragma(msg, m);
            static if( isFunction!( mixin( m ) ) )
                bool b = true;
        }
    }

    enum nothing = func!(typeof(this))();
    mixin(nothing);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




I've just this afternoon encountered another one that I can't work out a nice
way to discover:

struct S
{
  static int x;
}

bool b = isStatic!(S.x); // <- I can't think of a nice clean way to prove this
other than trying to assign to it, which is horrible.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065


Dmitry Olshansky <dmitry.olsh gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dmitry.olsh gmail.com



07:16:39 PST ---

 I've just this afternoon encountered another one that I can't work out a nice
 way to discover:
 
 struct S
 {
   static int x;
 }
 
 bool b = isStatic!(S.x); // <- I can't think of a nice clean way to prove this
 other than trying to assign to it, which is horrible.
Trying to take the address should do the trick. is(typeof(&S.x)) that is. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




---


 https://gist.github.com/4152297
I am seeing a few error cases: enum j { k = 10 } pragma(msg, isFunction!(j.k)); pragma(msg, isManifestConstant!(j.k)); pragma(msg, isPropertyFunction!(j.k)); pragma(msg, isVariable!(j.k)); These all throw errors.
Fixed.
  Kenji:
 
 I'm getting an error when using your new isFunction, here's the case:
 
 struct S
 {
     static string func(alias Class)()
     {
         foreach(m; __traits(allMembers, Class))
         {
             pragma(msg, m);
             static if( isFunction!( mixin( m ) ) )
                 bool b = true;
         }
     }
 
     enum nothing = func!(typeof(this))();
     mixin(nothing);
 }
This is a compiler bug, not an issue of isFunction template. I filed new bug 9083. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 Trying to take the address should do the trick. 
 is(typeof(&S.x)) that is.
That won't work for methods, but that might not be the use case. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 Trying to take the address should do the trick. 
 is(typeof(&S.x)) that is.
And if I have: S s; bool b = isStatic!(s.x); That solution doesn't work if 's' is an instance. I'm sick of writing really brittle code, I'm just saying that is another important std.traits. There's no trivial way to do this for an _anything_ that I can work out. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 That won't work for methods, but that might not be the use case.
Yeah, if it were in std.traits, I would expect it to work on methods too.

 I am seeing a few error cases:
 
 enum j { k = 10 }
 
 pragma(msg, isFunction!(j.k));
 pragma(msg, isManifestConstant!(j.k));
 pragma(msg, isPropertyFunction!(j.k));
 pragma(msg, isVariable!(j.k));
 
 These all throw errors.
Fixed.
Huzzah!
 This is a compiler bug, not an issue of isFunction template.
 I filed new bug 9083.
Amazing! You sir are awesome! :) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 This is a compiler bug, not an issue of isFunction template.
 I filed new bug 9083.
I found another one, probably a compiler bug too, but I'll paste it here since it depends on your new isVariable trait: Boiled down as much as I could... class Test { void func() { void templateFunc( T )( ref const T obj ) { foreach( m; __traits( allMembers, T ) ) { pragma(msg, m); static if( isVariable!( __traits(getMember, T, m) ) ) { //... } } } templateFunc( this ); } // some class members int x; } isVariable throws lots of errors when considering the class members. Note: __traits(allMembers, T) and __traits(getMember, T, m) These should also work with class instances, not just types, eg: __traits(allMembers, obj) and __traits(getMember, obj, m) And these combinations should also work: __traits(allMembers, T) and __traits(getMember, obj, m) __traits(allMembers, obj) and __traits(getMember, T, m) All these configurations throw errors, and the errors are different for each configuration. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065


Rob T <alanb ucora.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |alanb ucora.com





 What the compiler calls stuff internally has no bearing on
 what users of the language will call things.
It's not an internal thing, that declaration is not an enum declaration, period. enum is used as a keyword for more than one thing, which is bad, but it's too late to change it now. We shouldn't name things in Phobos based on what people might think is right or looks right, but based on what the things really are. It's a shame we don't have a 'manifest' keyword of some sort, it would help avoid confusion. I guess 'enum' was used to cut back on having too many keywords in the language. Anyway it's documented behavior, see "manifest constants" here (it's at the bottom): http://dlang.org/enum.html
As far as I was concerned, these are anonymous enum members in the case where there's only one member and the { } were omitted. I understood it in this way by reading the specification here: http://dlang.org/enum.html. It actual made some sense to me. The use of "manifest constant" terminology elsewhere will likely cause a lot of confusion. Why not term it as an "anonymous enum constant", or "enum manifest constant" if that suits the usage better. Term it anything so long as "enum" is in there so as to avoid the inevitable confusion elsewhere. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065







 What the compiler calls stuff internally has no bearing on
 what users of the language will call things.
It's not an internal thing, that declaration is not an enum declaration, period. enum is used as a keyword for more than one thing, which is bad, but it's too late to change it now. We shouldn't name things in Phobos based on what people might think is right or looks right, but based on what the things really are. It's a shame we don't have a 'manifest' keyword of some sort, it would help avoid confusion. I guess 'enum' was used to cut back on having too many keywords in the language. Anyway it's documented behavior, see "manifest constants" here (it's at the bottom): http://dlang.org/enum.html
As far as I was concerned, these are anonymous enum members in the case where there's only one member and the { } were omitted. I understood it in this way by reading the specification here: http://dlang.org/enum.html. It actual made some sense to me. The use of "manifest constant" terminology elsewhere will likely cause a lot of confusion. Why not term it as an "anonymous enum constant", or "enum manifest constant" if that suits the usage better. Term it anything so long as "enum" is in there so as to avoid the inevitable confusion elsewhere.
The history of this was: In D1, const XXX = YYY; declared a manifest constant. You couldn't take the address of it. With the change to const in D2, this no longer worked. I argued that we needed a way of doing manifest constants. Walter started implementing it as 'manifest'. Andrei argued for it to reuse 'enum' to reduce the number of keywords. Almost everybody was angry about overloading 'enum' and there was a huge fight, but Andrei won in the end. Yes it causes confusion. They are not enums, there is nothing enumerated about them. It's just an overloaded keyword. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 28 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 The history of this was:
 
 In D1, const XXX = YYY; declared a manifest constant. You couldn't take the
 address of it. With the change to const in D2, this no longer worked. I argued
 that we needed a way of doing manifest constants. Walter started implementing
 it as 'manifest'. Andrei argued for it to reuse 'enum' to reduce the number of
 keywords. Almost everybody was angry about overloading 'enum' and there was a
 huge fight, but Andrei won in the end. Yes it causes confusion.
 
 They are not enums, there is nothing enumerated about them. It's just an
 overloaded keyword.
Andrei was absolutely correct, as far as any user is concerned: enum E { K = 10 } // named enum enum { K = 10 } // anonymous enum enum K = 10; // obvious sugar to save bracket spam As said previously, I give exactly zero shits how it's implemented internally, or the history of it. The way it's documented now and the syntax chosen makes perfect sense, and any attempt to make K be somehow distinct in any of these cases is a mistake which will only lead to confusion. If E is an enum type, then K is an enum value, or an enum constant... (i like enum value better; 'constant' is verbose is implicit) Why would any normal user reasonably expect the term 'manifest' (which I still have no idea what it means) to appear in this context? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 28 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 The history of this was:
 
 In D1, const XXX = YYY; declared a manifest constant. You couldn't take the
 address of it. With the change to const in D2, this no longer worked. I argued
 that we needed a way of doing manifest constants. Walter started implementing
 it as 'manifest'. Andrei argued for it to reuse 'enum' to reduce the number of
 keywords. Almost everybody was angry about overloading 'enum' and there was a
 huge fight, but Andrei won in the end. Yes it causes confusion.
 
 They are not enums, there is nothing enumerated about them. It's just an
 overloaded keyword.
Interesting history, but the thing is that from a D users POV, it is a member of an anonymous enum, and that does not change however it may be internally represented, or historically thought of. I look at it this way enum { a = 2 } // anonymous enum set to 2 with one member enum a = 2; // anonymous enum set to 2 with one member and optional {} removed enum a; // anonymous enum unset with one member and optional {} removed How is this not what the specification says it is? How it may be internally represented is invisible to the user, what the user sees is only what is seen in terms of how the language represents the concept. This is an enum, and if it is not, then that only matters if it does not behave like all the other enum members, otherwise it may as well be viewed as if it is an enum member. I suspect this was Andrei's argument, because it actually does fit nicely into place. If I'm going to get mentally confabulated again because it does not work as I would expect an enum to work, then I'll be up in arms about it for sure, so I'm interested in knowing exactly how it is not like an enum, not internally, not historically, but in terms of usage from a programmers POV? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 28 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




03:06:54 PST ---

 interested in knowing exactly how it is not like an enum, not internally, not
 historically, but in terms of usage from a programmers POV?
It doesn't enumerate anything? Enumerations are collections of items, aren't they? How is one element a collection? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 28 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065






 interested in knowing exactly how it is not like an enum, not internally, not
 historically, but in terms of usage from a programmers POV?
It doesn't enumerate anything? Enumerations are collections of items, aren't they? How is one element a collection?
Then you need to disallow assigning explicit values to enum keys, that's not strictly an enumeration either. It just so happens that anonymous enums containing only a single value have a nice little sugar such that you don't need to write the brackets. This is because, in practise, this turns out to be a surprisingly common usage case so the little sugar is nice. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 28 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065







 interested in knowing exactly how it is not like an enum, not internally, not
 historically, but in terms of usage from a programmers POV?
It doesn't enumerate anything? Enumerations are collections of items, aren't they? How is one element a collection?
Then you need to disallow assigning explicit values to enum keys, that's not strictly an enumeration either. It just so happens that anonymous enums containing only a single value have a nice little sugar such that you don't need to write the brackets. This is because, in practise, this turns out to be a surprisingly common usage case so the little sugar is nice.
I believe the similarity you've listed is false. An enumerated type must be integral (it must be countable!) A manifest constant, however, can be anything - a struct literal, for example. I think what has happened is that C had a very sloppy enum design, where it mixed integral manifest constants with enumerated types. Instead of tightening up 'enum', we used the existing sloppiness as an excuse to make it worse. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 28 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065





 I believe the similarity you've listed is false. An enumerated type must be
 integral (it must be countable!) A manifest constant, however, can be anything
 - a struct literal, for example.
... really? But D supports typing enums: enum E : string { X = "hello", Y = "world" } I tried: enum E : string { X = "hello", Y } Sure, this would normally try and increment by one, but since it's not integral I got this error: incompatible types for (("hello") + (1)): 'S' and 'int' Makes perfect sense to me, apparently you just lose the auto-increment behaviour if the enums are not an integeral type? (although the error message could be clearer) So perhaps you mean, "must be integral if you want auto-increment behaviour"? Often enough you don't even want auto-increment, you want a collection of meaningful pre-defined values, I think that's just as good a definition of the term 'enumeration', auto-increment is not fundamental to this enumerated type concept in my mind. In fact, I think I might even use all-explicit values more often than auto-incremented ones in my code.
 I think what has happened is that C had a very sloppy enum design, where it
 mixed integral manifest constants with enumerated types. Instead of tightening
 up 'enum', we used the existing sloppiness as an excuse to make it worse.
Worse? It's perfect... >_< -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 28 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




Can I just add, we've derailed my actual bug thread here >_<

This is an extremely important issue for me, which has been lost in the meaning
of enum and whether 'manifest constant' is a stupid name or not.

Any word on isStatic!(), good/bad one to have (I don't know how to do it
manually)?

These traits are of critical importance to me to help a bunch of non-D
programmers feel that the language is awesome and intuitive; ie, 'can
understand it when they read the code', and assure it is maintainable going
forward.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 28 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9065




PST ---
 An enumerated type must be integral (it must be countable!)
This is not true at all in D. An enum can be any type which can be compared and can be use to directly initialize a variable at compile time. On top of that including built-in types like strings, TDPL specifically talks about declaring enums which are structs - and that's enums with a list of values, not manifest constants. It's incredibly valuable to be able to have enumerated lists of user-defined tpes rather than just integral values. I have no problem whatsoever calling enums which are manifest constants manifest constants rather than enums, but at the same time, the only differences between them and normal enums are the fact that they don't have a separate enum type and there's only one of them. Practically speaking, there's really no other difference. Neither have addresses. They're just values that get copy-pasted when used. So, while I have no problem with the term manifest constant, I don't think that it would cause any real problem to refer to them as anonymous enums instead. I do kind of wish that we'd gone with the keyword manifest over enum to better separate the two concepts, because manifest constants are actually enumerated, but from a pratical point of view, it's really a non-issue IMHO. If anything, normal enums are simply an enumeration of manifest constants. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 28 2012