November 25, 2018
On Sunday, 25 November 2018 at 05:41:56 UTC, H. S. Teoh wrote:
> On Sat, Nov 24, 2018 at 05:48:16PM +0000, Stanislav Blinov via Digitalmars-d-learn wrote:

>> Yup. UDAs did get in there eventually, and version should too.
>
> I think this would be a trivial DIP, by making it such that a version block inside an enum would lower to the above code. Of course, it could be taken further: the above trick doesn't quite handle this case:
>
> 	enum E {
> 		a,
> 		version(Windows) {
> 			b, c
> 		}
> 		version(Posix) {
> 			d
> 		}
> 	}

That is what Jonathan (and I concur) is talking about.

> But this looks like such an antipattern that it probably should be written differently anyway, or just generated via a string mixin.

Why is it an antipattern? Having to version the whole enum just because some stupid C API has two out of a hundred items versioned per platform is an antipattern :)

Granted, it may require some special syntax, i.e.

enum E {
    a,
    b if version(Windows),
    c if version(Windows),
    d if version(Posix),
}

or something to that effect. But there has to be a better way than just versioning the whole enum or resorting to clumsy mixins.
November 25, 2018
On Sunday, 25 November 2018 at 07:19:50 UTC, Stanislav Blinov wrote:

> Granted, it may require some special syntax, i.e.
>
> enum E {
>     a,
>     b if version(Windows),
>     c if version(Windows),
>     d if version(Posix),
> }
>
> or something to that effect.

Come to think of it, since UDAs are now allowed, the compiler could potentially be taught this:

enum E {
    a,
    @version(Windows) b,
    @version(Windows) c,
    @version(Posix)   d,
}
November 25, 2018
On Saturday, November 24, 2018 10:41:56 PM MST H. S. Teoh via Digitalmars-d- learn wrote:
> On Sat, Nov 24, 2018 at 05:48:16PM +0000, Stanislav Blinov via
Digitalmars-d-learn wrote:
> > On Saturday, 24 November 2018 at 17:43:35 UTC, Jonathan M Davis wrote:
> > > I'm still inclined to think though that it should be legal to just use version directly in the member list.
> >
> > Yup. UDAs did get in there eventually, and version should too.
>
> I think this would be a trivial DIP, by making it such that a version block inside an enum would lower to the above code. Of course, it could be taken further: the above trick doesn't quite handle this case:
>
>   enum E {
>       a,
>       version(Windows) {
>           b, c
>       }
>       version(Posix) {
>           d
>       }
>   }
>
> But this looks like such an antipattern that it probably should be written differently anyway, or just generated via a string mixin.

It's something that comes up fairly frequently actually when dealing with system APIs. For instance, if you want your socket API to provide the full functionality of the underlying C API, then you're going to have to provide not only differing enum values for things like socket options or socket family, but you're actually going to have to provide different enum members in some cases.

So, sure, if you're writing something that's purely D and can be properly platform-agnostic, then having different enum members for different platforms would be bad, but once C APIs get involved, I definitely would not consider it to be an anti-pattern. At that point, it has a tendency to become a necessity, and I've had several occasions where being able to version enum members would have made the code shorter. It also would have eliminated the need for version(D_Ddoc) (or the druntime or Phobos equivalents).

- Jonathan M Davis



November 25, 2018
On Sun, Nov 25, 2018 at 07:22:54AM +0000, Stanislav Blinov via Digitalmars-d-learn wrote:
> On Sunday, 25 November 2018 at 07:19:50 UTC, Stanislav Blinov wrote:
> 
> > Granted, it may require some special syntax, i.e.
> > 
> > enum E {
> >     a,
> >     b if version(Windows),
> >     c if version(Windows),
> >     d if version(Posix),
> > }
> > 
> > or something to that effect.
> 
> Come to think of it, since UDAs are now allowed, the compiler could potentially be taught this:
> 
> enum E {
>     a,
>     @version(Windows) b,
>     @version(Windows) c,
>     @version(Posix)   d,
> }

Actually, I just thought of a way to do this with the existing language: use a struct to simulate an enum:

	struct E {
		alias Basetype = int;
		Basetype impl;
		alias impl this;

		enum a = E(1);
		enum b = E(2);
		version(Windows) {
			enum c = E(3);
		}
		version(Posix) {
			enum c = E(4);
			enum d = E(100);
		}
	}

It's not 100% the same thing, but gets pretty close, e.g., you can reference enum values as E.a, E.b, you can declare variables of type E and pass it to functions and it implicitly converts to the base type, etc..

There are some differences, like cast(E) won't work like an enum, and .max has to be manually declared, etc.. You'll also need to explicitly assign values to each member, but for OS-dependent enums you have to do that already anyway.


T

-- 
Let's eat some disquits while we format the biskettes.
November 25, 2018
On Sunday, 25 November 2018 at 21:38:43 UTC, H. S. Teoh wrote:

> Actually, I just thought of a way to do this with the existing language: use a struct to simulate an enum:
>
> 	struct E {
> 		alias Basetype = int;
> 		Basetype impl;
> 		alias impl this;
>
> 		enum a = E(1);
> 		enum b = E(2);
> 		version(Windows) {
> 			enum c = E(3);
> 		}
> 		version(Posix) {
> 			enum c = E(4);
> 			enum d = E(100);
> 		}
> 	}

Heh, that can work in a pinch. Disgusting though :D

> It's not 100% the same thing, but gets pretty close, e.g., you can reference enum values as E.a, E.b, you can declare variables of type E and pass it to functions and it implicitly converts to the base type, etc..
>
> There are some differences, like cast(E) won't work like an enum...

It should, you can cast values of same sizeof to a struct.

> and .max has to be manually declared, etc.. You'll also need to explicitly assign values to each member, but for OS-dependent enums you have to do that already anyway.

Yeah, those aren't a huge concern for that particular scenario.
November 26, 2018
On Sun, Nov 25, 2018 at 09:53:50PM +0000, Stanislav Blinov via Digitalmars-d-learn wrote:
> On Sunday, 25 November 2018 at 21:38:43 UTC, H. S. Teoh wrote:
> 
> > Actually, I just thought of a way to do this with the existing language: use a struct to simulate an enum:
> > 
> > 	struct E {
> > 		alias Basetype = int;
> > 		Basetype impl;
> > 		alias impl this;
> > 
> > 		enum a = E(1);
> > 		enum b = E(2);
> > 		version(Windows) {
> > 			enum c = E(3);
> > 		}
> > 		version(Posix) {
> > 			enum c = E(4);
> > 			enum d = E(100);
> > 		}
> > 	}
> 
> Heh, that can work in a pinch. Disgusting though :D

I dunno, given that D structs are supposed to be "glorified ints" according to TDPL, I see enum declarations more-or-less as a shorthand for structs of the above sort. :-D  Much like template functions / enums / etc. are shorthands for eponymous templates.


> > It's not 100% the same thing, but gets pretty close, e.g., you can reference enum values as E.a, E.b, you can declare variables of type E and pass it to functions and it implicitly converts to the base type, etc..
> > 
> > There are some differences, like cast(E) won't work like an enum...
> 
> It should, you can cast values of same sizeof to a struct.
[...]

Haha, didn't know that.


T

-- 
Dogs have owners ... cats have staff. -- Krista Casada
1 2 3
Next ›   Last »