Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 04, 2012 "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
One of the issues I've been running into more or less frequently lately is the inability to extract an instance of a type when trying to do conditional implementation specification. Let me explain myself. Using T.init is a no go, because: a) T might be "@disabled this()", making T.init illegal syntax (in theory, currently "buggy") b) T.init is NOT an LValue, making code such is "is(typeof(T.init = 5))" invalid c) You can try to use "T t = void", but you may also run into problems: c)1) If T is immutable, that's illegal. c)2) The compiler may complain if you use t, due to access to uninitialized. This makes it a pain in the ass, as shown in this thread: http://forum.dlang.org/thread/mailman.224.1348358069.5162.digitalmars-d-learn@puremagic.com Or this pull request: https://github.com/D-Programming-Language/phobos/pull/832 The current implementation for "isAssignable" is //---- template isAssignable(Lhs, Rhs) { enum bool isAssignable = is(typeof({ Lhs l = void; void f(Rhs r) { l = r; } return l; })); } //---- The code is correct, but when you have to jump through that many loops, you have to admit there is probably something wrong. Imagine you are writting a template "Foo" that only works if it is legal to pass an instance of T to a function Bar. Are you *really* going to write the same thing as above, inside a single conditional if?! //****************************************** I'd like to propose an "instanceOf(T)" traits template, that would return an LValue instance of T. It would be used (strictly) for evaluating conditional implementations, or for the implementation of traits types. //---- template instanceOf(T) { static if (is(typeof({T t;}))) T instanceOf; else T instanceOf = void; } //---- Now, watch this //---- template isAssignable(T, U) { enum bool isAssignable = is(typeof(instanceOf!T = instanceOf!U)); } struct S { @disable this(); } void main() { static assert( isAssignable!(int, int)); static assert( isAssignable!(int, immutable(int))); static assert(!isAssignable!(immutable(int), int)); static assert( isAssignable!(S, immutable(S))); //Tricky test BTW } //---- See? Easy peasy. And this is just a "simple" test case: assign-ability. There are a bunch of other traits templates which would benefit here. And that's the "tip of the iceberg": There are a TON of algorithms that use .init in their implementation restrictions: "if (Range.init.front ...)" instanceOf would be a convenient way to support any type, regardless of construct-ability (or lack thereof). //-------- That's my idea anyways, they've been consistently destroyed recently, so I don't mind again if you think it is a bad idea, or the approach is wrong. I *do* think that being able to extract an instance of a type without worrying about how to actually acquire one... |
October 04, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Thursday, 4 October 2012 at 09:43:08 UTC, monarch_dodra wrote:
> [SNIP]
You know what? Forget I said anything? Using lambdas is an incredibly good workaround for all the problems stated above, making the initial point moot.
Lamba if:
template isAssignable(T, U)
{
enum bool isAssignable =
is(typeof((ref T t, ref U u) => {t = u;}));
}
This allow testing on t and u, without ever having to construct/acquire them. Neat-o!!!
|
October 04, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Thursday, 4 October 2012 at 09:43:08 UTC, monarch_dodra wrote:
> The current implementation for "isAssignable" is
> //----
> template isAssignable(Lhs, Rhs)
> {
> enum bool isAssignable = is(typeof({
> Lhs l = void;
> void f(Rhs r) { l = r; }
> return l;
> }));
> }
OT - Is there any reason for disabling UFCS for this?
template isAssignable(Lhs, Rhs)
{
enum bool isAssignable =
{
Lhs l = void;
void f(Rhs r) { l = r; }
return l;
}.typeof.is;
}
|
October 04, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to so | On Thursday, 4 October 2012 at 12:48:51 UTC, so wrote:
> On Thursday, 4 October 2012 at 09:43:08 UTC, monarch_dodra wrote:
>
>> The current implementation for "isAssignable" is
>> //----
>> template isAssignable(Lhs, Rhs)
>> {
>> enum bool isAssignable = is(typeof({
>> Lhs l = void;
>> void f(Rhs r) { l = r; }
>> return l;
>> }));
>> }
>
> OT - Is there any reason for disabling UFCS for this?
>
> template isAssignable(Lhs, Rhs)
> {
> enum bool isAssignable =
> {
> Lhs l = void;
> void f(Rhs r) { l = r; }
> return l;
> }.typeof.is;
> }
Because typeof is a keyword, and is is a declaration.
There are two open ER to allow typeof to be used as a property: While not strictly EFCS, it would be convenient.
Regarding is, There are no open requests. But I guess it would be fun to write
if( T.is(U) ).
But where would it end? Make if UFCS too?
T.is(U).if()
IMO, I can see typeof being a property, but not is.
|
October 04, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | 2012/10/4 monarch_dodra <monarchdodra@gmail.com>: > One of the issues I've been running into more or less frequently lately is the inability to extract an instance of a type when trying to do conditional implementation specification. > > Let me explain myself. Using T.init is a no go, because: > a) T might be "@disabled this()", making T.init illegal syntax (in theory, > currently "buggy") I think T.init should always legal. > b) T.init is NOT an LValue, making code such is "is(typeof(T.init = 5))" > invalid > c) You can try to use "T t = void", but you may also run into problems: > c)1) If T is immutable, that's illegal. > c)2) The compiler may complain if you use t, due to access to uninitialized. IMO, this is just a compiler bug. If a variable has VoidInitializer, it should always become a runtime value. Kenji Hara |
October 04, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to kenji hara | On Thursday, 4 October 2012 at 17:44:48 UTC, kenji hara wrote:
>> a) T might be "@disabled this()", making T.init illegal syntax (in theory,
>> currently "buggy")
>
> I think T.init should always legal.
What would be the semantics of T.init for a type with @disable this()? It isn't a valid value, for sure...
David
|
October 04, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 2012-37-04 11:10, monarch_dodra <monarchdodra@gmail.com> wrote: > One of the issues I've been running into more or less frequently lately is the inability to extract an instance of a type when trying to do conditional implementation specification. > > Let me explain myself. Using T.init is a no go, because: > a) T might be "@disabled this()", making T.init illegal syntax (in theory, currently "buggy") > b) T.init is NOT an LValue, making code such is "is(typeof(T.init = 5))" invalid > c) You can try to use "T t = void", but you may also run into problems: > c)1) If T is immutable, that's illegal. > c)2) The compiler may complain if you use t, due to access to uninitialized. [snip: Good stuff] I like this, and have had the exact same thought. There is one thing I don't like, and that is your instanceOf could be used to create an uninitialized T. In the interest of that (and brevity) let me present my solution: @property T instanceOf( T )( ); It works great in static if, and fails at link-time. The error message is however far from perfect: Error 42: Symbol Undefined _D3foo24__T10instanceOfTS3foo1SZ10instanceOfFNdZS3foo1S But I think that is better than giving developers a tool for instantiating types that are not meant to be instantiated. -- Simen |
October 04, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | On Thursday, 4 October 2012 at 17:57:51 UTC, Simen Kjaeraas wrote:
> [SNIP]
>
> @property T instanceOf( T )( );
>
> [SNIP]
Awesome! It is much more robust too! I still don't understand how
*my* instanceOf!(immutable(S)) works :/
I'd just change it to:
@property ref T instanceOf( T )( );
So that instanceOf acts as an LValue.
Having a link error is great too. A compile error would be best,
but unachievable actually, so still pretty good.
|
October 05, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Thursday, 4 October 2012 at 09:43:08 UTC, monarch_dodra wrote: > [SNIP] An ER has been opened. http://d.puremagic.com/issues/show_bug.cgi?id=8762 |
October 10, 2012 Re: "instanceOf" trait for conditional implementations | ||||
---|---|---|---|---|
| ||||
Posted in reply to so | Am Thu, 04 Oct 2012 14:43:00 +0200 schrieb "so" <so@so.so>: > OT - Is there any reason for disabling UFCS for this? > > template isAssignable(Lhs, Rhs) > { > enum bool isAssignable = > { > Lhs l = void; > void f(Rhs r) { l = r; } > return l; > }.typeof.is; > } Yoda says: "This proposal a special type of is!" -- Marco |
Copyright © 1999-2021 by the D Language Foundation