Re: How to search for an enum by values and why enum items aren't unique

2016-07-27 Thread Ali Çehreli via Digitalmars-d-learn

On 07/27/2016 08:42 AM, stunaep wrote:

On Wednesday, 27 July 2016 at 15:32:59 UTC, Meta wrote:

On Wednesday, 27 July 2016 at 13:59:54 UTC, stunaep wrote:

So how would I make a function that takes an enum and an id as a
parameter and returns a member in the enum? I tried for quite some
time to do this but it wont let me pass Test as a parameter unless I
use templates. I finally came up with this but it wont let me return
null when there's nothing found


E findEnumMember(E)(int id) if (is(E == enum)) {
auto found = [EnumMembers!E].find!(a => a.id == id)();
if(!found.empty)
return found.front;
else
...What do I return? null gives error
}


If you're going to do it like this your only real options are to
return a Nullable!E or throw an exception if the id isn't found.


I tried Nullable!E earlier and it didnt work.


import std.traits;
import std.algorithm;
import std.array;
import std.typecons;

Nullable!E findEnumMember(E)(int id) if (is(E == enum)) {
auto found = [EnumMembers!E].find!(a => a.id == id)();
if(!found.empty)
return Nullable!E(found.front);
else
return Nullable!E();
}

struct S {
int id;
}

enum MyEnum : S {
x = S(42),
invalid = S()// Useful for the other alternative
}

void main() {
auto a = findEnumMember!MyEnum(42);
assert(!a.isNull);
auto b = findEnumMember!MyEnum(7);
assert(b.isNull);
}



I dont need it to be done
like this, it just has to be done someway. I'm asking for help because
that's the only way I could think of.


Another alternative is to require that the enum has a special sentinel:

else
return E.invalid;

Ali



Re: How to search for an enum by values and why enum items aren't unique

2016-07-27 Thread stunaep via Digitalmars-d-learn

On Wednesday, 27 July 2016 at 15:32:59 UTC, Meta wrote:

On Wednesday, 27 July 2016 at 13:59:54 UTC, stunaep wrote:
So how would I make a function that takes an enum and an id as 
a parameter and returns a member in the enum? I tried for 
quite some time to do this but it wont let me pass Test as a 
parameter unless I use templates. I finally came up with this 
but it wont let me return null when there's nothing found



E findEnumMember(E)(int id) if (is(E == enum)) {
auto found = [EnumMembers!E].find!(a => a.id == id)();
if(!found.empty)
return found.front;
else
...What do I return? null gives error
}


If you're going to do it like this your only real options are 
to return a Nullable!E or throw an exception if the id isn't 
found.


I tried Nullable!E earlier and it didnt work. I dont need it to 
be done like this, it just has to be done someway. I'm asking for 
help because that's the only way I could think of.


Re: How to search for an enum by values and why enum items aren't unique

2016-07-27 Thread Meta via Digitalmars-d-learn

On Wednesday, 27 July 2016 at 13:59:54 UTC, stunaep wrote:
So how would I make a function that takes an enum and an id as 
a parameter and returns a member in the enum? I tried for quite 
some time to do this but it wont let me pass Test as a 
parameter unless I use templates. I finally came up with this 
but it wont let me return null when there's nothing found



E findEnumMember(E)(int id) if (is(E == enum)) {
auto found = [EnumMembers!E].find!(a => a.id == id)();
if(!found.empty)
return found.front;
else
...What do I return? null gives error
}


If you're going to do it like this your only real options are to 
return a Nullable!E or throw an exception if the id isn't found.


Re: How to search for an enum by values and why enum items aren't unique

2016-07-27 Thread stunaep via Digitalmars-d-learn
On Wednesday, 20 July 2016 at 05:45:21 UTC, Jonathan M Davis 
wrote:
On Wednesday, July 20, 2016 04:03:23 stunaep via 
Digitalmars-d-learn wrote:

How can I search for an enum by its values? For example I have

>struct TestTraits {
>
> int value1;
> string value2;
>
>}
>
>enum Test : TestTraits {
>
> TEST = TestTraits(1, "test1"),
> TESTING = TestTraits(5, "test5")
>
>}

and I have the int 5 and need to find TESTING with it.

In java I would create a SearchableEnum interface, make all 
searchable enums implement it and use this method to find them.


>public static  T find(T[] vals, int
>id) {
>
> for (T val : vals) {
>
> if (id == val.getId()) {
>
> return val;
>
> }
>
> }
> return null;
>
>}

But the way enums work in D doesn't seem to permit this.


If you want the list of members in an enum, then use 
std.traits.EnumMembers and you'll get a compile-time list of 
them. It can be made into a runtime list by being put into an 
array literal.


For instance, if we take std.datetime.Month, we can look for 
the enum with the value 10 in it like so.


auto found = [EnumMembers!Month].find(10);
assert(found = [Month.oct, Month.nov, Month.dec]);

So, if you had your TestTraits struct as the type for an enum, 
you could do something like


auto found = [EnumMembers!TestTraits].find!(a => a.value1 == 
5)();

if(found.empty)
{
// there is no TestTraits which matches
}
else
{
// found.front is the match
}

And why on earth are different enum items with the same values 
equal to each other? Say I have an enum called DrawableShape


Because they have the same value. The fact that they're enums 
doesn't change how they're compared. That's determined by what 
type they are. All you're really getting with an enum is a list 
of named constants that are grouped together which implicitly 
convert to their base type but which are not converted to 
implicitly from their base type. The only stuff that's going to 
treat an enum member differently from any other value of that 
type is something that specifically operates on enums - e.g. by 
taking the enum type explicitly, or because it has is(T == 
enum) and does something different for enums (quite a few 
traits do that in std.traits), or because it uses a final 
switch. Most code is just going to treat them like any other 
value of the enum's base type. They aren't magically treated as 
unique in some way just because they're in an enum.


- Jonathan M Davis


So how would I make a function that takes an enum and an id as a 
parameter and returns a member in the enum? I tried for quite 
some time to do this but it wont let me pass Test as a parameter 
unless I use templates. I finally came up with this but it wont 
let me return null when there's nothing found



E findEnumMember(E)(int id) if (is(E == enum)) {
auto found = [EnumMembers!E].find!(a => a.id == id)();
if(!found.empty)
return found.front;
else
...What do I return? null gives error
}


Re: How to search for an enum by values and why enum items aren't unique

2016-07-20 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, July 20, 2016 18:08:14 stunaep via Digitalmars-d-learn wrote:
> On Wednesday, 20 July 2016 at 05:45:21 UTC, Jonathan M Davis
>
> wrote:
> > On Wednesday, July 20, 2016 04:03:23 stunaep via
> >
> > Digitalmars-d-learn wrote:
> >> [...]
> >
> > If you want the list of members in an enum, then use
> > std.traits.EnumMembers and you'll get a compile-time list of
> > them. It can be made into a runtime list by being put into an
> > array literal.
> >
> > [...]
>
> Coming from Java I've learned to love enums that are separate
> objects, that can store multiple values, and that can have
> methods that can be in their scope. Seems to me like there's no
> reason to even use enums in D. What's the point when just making
> a constant would do the same exact thing?

Many languages with enums don't even have the ability to have user-defined
types be enum members, and yet many folks find them to be very useful. So,
the fact that you can declare an enum of structs in D is a huge step up over
many languages just like Java's ability to use classes with enums is a shuge
step over such languages. But regardless of the language, pretty much the
whole point of an enum is to group a set of constants together. So, you can
do things like have

enum DayOfWeek : ubyte { sun = 0,
 mon,
 tue,
 wed,
 thu,
 fri,
 sat
   }

or

enum AddressFamily : int
{
unspec = AF_UNSPEC,
unix = AF_UNIX,
inet = AF_INET,
inet6 = AF_INET6,
}

and then code can deal with them as being associated rather than just a
bunch of constants with values that happen to be related. It also makes it
more obvious to programmers that they're related. You
can do stuff like

auto foo(AddressFamily af) {...}

and then foo clearly accepts the values in AddressFamily and not just any
random int. You can do stuff like

final switch(myEnum)
{
case MyEnum.a: ...
case MyEnum.b: ...
case MyEnum.c: ...
}

and then get a compilation error when a new member is added to the enum so
that you catch that it wasn't added to the switch. You can get the list of
them together via EnumMembers. stuff like std.conv.to and writeln use the
names of the enum members, not their values. So, they're far more than just
constants with particular values.

If all you need is a few constants and don't care that they have anything to
do with one another, then you don't need to declare an enum. But if you want
to be able to group them such that they're treated as a group, then enums
are great. The fact that you can then have some which are user-defined types
is a great bonus, but it's far from the core aspect of what makes an enum
and makes them useful. Similarly, while it is frequently the case that you
want the enum members to be unique, it's also sometimes the case that you
_don't_ want them to be unique. In general it's the ability to have a group
of associated constants which is what makes enums so valuable, and whether
something like uniqueness or member functions is important depends on the
particular enum and what you're doing with it.

- Jonathan M Davis



Re: How to search for an enum by values and why enum items aren't unique

2016-07-20 Thread Lodovico Giaretta via Digitalmars-d-learn

On Wednesday, 20 July 2016 at 18:08:14 UTC, stunaep wrote:
On Wednesday, 20 July 2016 at 05:45:21 UTC, Jonathan M Davis 
wrote:
On Wednesday, July 20, 2016 04:03:23 stunaep via 
Digitalmars-d-learn wrote:

[...]


If you want the list of members in an enum, then use 
std.traits.EnumMembers and you'll get a compile-time list of 
them. It can be made into a runtime list by being put into an 
array literal.


[...]


Coming from Java I've learned to love enums that are separate 
objects, that can store multiple values, and that can have 
methods that can be in their scope. Seems to me like there's no 
reason to even use enums in D. What's the point when just 
making a constant would do the same exact thing?


You can easily emulate Java enums in D.

class MyEnumClass
{
// fields and methods, as a class
private int val;
public int foo()
{
 return val * 2;
}

// private ctor: user cannot instantiate the class
private this(int i)
{
val = i;
}

// your enumerated instances
static immutable ONE;
static immutable TWO;
static immutable THREE;

// initialize the enumerate values on program startup
shared static this()
{
ONE = new MyEnumClass(1);
TWO = new MyEnumClass(2);
THREE = new MyEnumClass(3);
}
}

It's not much longer than the equivalent Java code and is way 
clearer (you know exactly what's going on under the hood).


In java an enum is just an extension of the singleton pattern, 
where there's a finite set of instantiation instead of exactly 
one.


A D enum (or a C one, or a C++ one) is a totally different thing.


Re: How to search for an enum by values and why enum items aren't unique

2016-07-20 Thread Ali Çehreli via Digitalmars-d-learn

On 07/19/2016 09:03 PM, stunaep wrote:

> And why on earth are different enum items with the same values
> equal to each other?

I've seen code where it made sense. Searching for an example reveals:

enum Scope
{
Transient,
Singleton,
Default=Transient
}

> Seems to me like there's no reason to even use enums in D.

I don't know how they are used in Java but they are very common in 
C-style code like your if-else if chain is. (Equally useful with the 
switch statement). There are other ways of achieving the same thing; OOP 
is just one.


> What's the point when just making a constant would do the same
> exact thing?

enum groups a set of values under a type. For example, you can write a 
function that accepts enum Color and it expects just the values that it 
contains. I think it's useful.


Ali



Re: How to search for an enum by values and why enum items aren't unique

2016-07-20 Thread stunaep via Digitalmars-d-learn
On Wednesday, 20 July 2016 at 05:45:21 UTC, Jonathan M Davis 
wrote:
On Wednesday, July 20, 2016 04:03:23 stunaep via 
Digitalmars-d-learn wrote:

[...]


If you want the list of members in an enum, then use 
std.traits.EnumMembers and you'll get a compile-time list of 
them. It can be made into a runtime list by being put into an 
array literal.


[...]


Coming from Java I've learned to love enums that are separate 
objects, that can store multiple values, and that can have 
methods that can be in their scope. Seems to me like there's no 
reason to even use enums in D. What's the point when just making 
a constant would do the same exact thing?


Re: How to search for an enum by values and why enum items aren't unique

2016-07-19 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, July 20, 2016 04:03:23 stunaep via Digitalmars-d-learn wrote:
> How can I search for an enum by its values? For example I have
>
> >struct TestTraits {
> >
> > int value1;
> > string value2;
> >
> >}
> >
> >enum Test : TestTraits {
> >
> > TEST = TestTraits(1, "test1"),
> > TESTING = TestTraits(5, "test5")
> >
> >}
>
> and I have the int 5 and need to find TESTING with it.
>
> In java I would create a SearchableEnum interface, make all
> searchable enums implement it and use this method to find them.
>
> >public static  T find(T[] vals, int
> >id) {
> >
> > for (T val : vals) {
> >
> > if (id == val.getId()) {
> >
> > return val;
> >
> > }
> >
> > }
> > return null;
> >
> >}
>
> But the way enums work in D doesn't seem to permit this.

If you want the list of members in an enum, then use std.traits.EnumMembers
and you'll get a compile-time list of them. It can be made into a runtime
list by being put into an array literal.

For instance, if we take std.datetime.Month, we can look for the enum
with the value 10 in it like so.

auto found = [EnumMembers!Month].find(10);
assert(found = [Month.oct, Month.nov, Month.dec]);

So, if you had your TestTraits struct as the type for an enum, you could do
something like

auto found = [EnumMembers!TestTraits].find!(a => a.value1 == 5)();
if(found.empty)
{
// there is no TestTraits which matches
}
else
{
// found.front is the match
}

> And why on earth are different enum items with the same values
> equal to each other? Say I have an enum called DrawableShape

Because they have the same value. The fact that they're enums doesn't change
how they're compared. That's determined by what type they are. All you're
really getting with an enum is a list of named constants that are grouped
together which implicitly convert to their base type but which are not
converted to implicitly from their base type. The only stuff that's going to
treat an enum member differently from any other value of that type is
something that specifically operates on enums - e.g. by taking the enum type
explicitly, or because it has is(T == enum) and does something different for
enums (quite a few traits do that in std.traits), or because it uses a final
switch. Most code is just going to treat them like any other value of the
enum's base type. They aren't magically treated as unique in some way just
because they're in an enum.

- Jonathan M Davis



How to search for an enum by values and why enum items aren't unique

2016-07-19 Thread stunaep via Digitalmars-d-learn

How can I search for an enum by its values? For example I have

struct TestTraits {
int value1;
string value2;
}

enum Test : TestTraits {
TEST = TestTraits(1, "test1"),
TESTING = TestTraits(5, "test5")
}


and I have the int 5 and need to find TESTING with it.

In java I would create a SearchableEnum interface, make all 
searchable enums implement it and use this method to find them.
public static  T find(T[] vals, int 
id) {

for (T val : vals) {
if (id == val.getId()) {
return val;
}
}
return null;
}

But the way enums work in D doesn't seem to permit this.

And why on earth are different enum items with the same values 
equal to each other? Say I have an enum called DrawableShape



struct DrawableShapeTraits {
bool useAlpha;
int sideCount;
}

enum DrawableShape : DrawableShapeTraits {
RECTANGLE = DrawableShapeTraits(true, 4),
DIAMOND = DrawableShapeTraits(true, 4),
}


Now say I have some code that does this


if(shape == DrawableShape.DIAMOND)
... render a diamond
else if(shape == DrawableShape.RECTANGLE)
... render a rectangle


Now even if shape is a DrawableShape.RECTANGLE it's going to 
render a DrawableShape.DIAMOND unless I add a dummy value to 
differentiate them.