Thread overview
"instanceOf" trait for conditional implementations
Oct 04, 2012
monarch_dodra
Oct 04, 2012
monarch_dodra
Oct 04, 2012
so
Oct 04, 2012
monarch_dodra
Oct 10, 2012
Marco Leise
Oct 04, 2012
kenji hara
Oct 04, 2012
David Nadlinger
Oct 04, 2012
Simen Kjaeraas
Oct 04, 2012
monarch_dodra
Oct 05, 2012
monarch_dodra
October 04, 2012
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
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
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
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
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
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
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
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
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
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