Jump to page: 1 2 3
Thread overview
opDispatch and compile time parameters
Oct 17, 2015
Nikolay
Oct 17, 2015
Meta
Oct 19, 2015
David Osborne
Oct 19, 2015
Jack Applegame
Oct 19, 2015
Nikolay
Oct 19, 2015
Adam D. Ruppe
Oct 19, 2015
Jonathan M Davis
Oct 19, 2015
Adam D. Ruppe
Oct 19, 2015
Timon Gehr
Oct 20, 2015
Jonathan M Davis
Oct 20, 2015
Marc Schütz
Oct 20, 2015
Jonathan M Davis
Oct 21, 2015
Timon Gehr
Oct 21, 2015
Don
Oct 21, 2015
Timon Gehr
Oct 21, 2015
Jonathan M Davis
Oct 21, 2015
Nikolay
Oct 19, 2015
Jack Applegame
Nov 14, 2015
Jakob Ovrum
October 17, 2015
I asked on SO question about opDispatch and compile time parameters: http://stackoverflow.com/questions/32998781/opdispatch-and-compile-time-parameters

Currently it looks like it is not possible to use opDispatch for non trivial template functions. I think opDispatch should get function name plus evaluated compile time arguments as first compile time parameter. E.g not just function name "b", but "b.p2!(int, 10)"  See example from SO question:

import std.stdio;

class B{
    auto p1(T)(T arg) {
        writeln( "p1: ", arg );
    }
    auto p2(T, int C)(T s) {
        writeln( "p2: ", s, " / ", C);
    }
}

class C(T) {
    T b = new T;

    auto opDispatch(string s, Args...)(Args args) {
       mixin("b."~s)(args);
    }
}

void main() {
    auto b = new C!(B)();
    //fine: compiler is smart enough
    b.p1("abc");
    //oops: "no property 'p2' for type ..."
    b.p2!(int, 10)(5);
    auto origB = new B;
    //fine:
    origB.p2!(int, 10)(5);
}

Is it good idea for opDispatch improvement or may there is some other approach?
October 17, 2015
On Saturday, 17 October 2015 at 15:31:00 UTC, Nikolay wrote:
> I asked on SO question about opDispatch and compile time parameters: http://stackoverflow.com/questions/32998781/opdispatch-and-compile-time-parameters
>
> Currently it looks like it is not possible to use opDispatch for non trivial template functions. I think opDispatch should get function name plus evaluated compile time arguments as first compile time parameter. E.g not just function name "b", but "b.p2!(int, 10)"  See example from SO question:
>
> import std.stdio;
>
> class B{
>     auto p1(T)(T arg) {
>         writeln( "p1: ", arg );
>     }
>     auto p2(T, int C)(T s) {
>         writeln( "p2: ", s, " / ", C);
>     }
> }
>
> class C(T) {
>     T b = new T;
>
>     auto opDispatch(string s, Args...)(Args args) {
>        mixin("b."~s)(args);
>     }
> }
>
> void main() {
>     auto b = new C!(B)();
>     //fine: compiler is smart enough
>     b.p1("abc");
>     //oops: "no property 'p2' for type ..."
>     b.p2!(int, 10)(5);
>     auto origB = new B;
>     //fine:
>     origB.p2!(int, 10)(5);
> }
>
> Is it good idea for opDispatch improvement or may there is some other approach?

There is another approach, which is to automatically generate a declaration that more or less matches the one in b. Then you can call b.p2 or whatever else on the outer class, and it will be forwarded to the inner class. The implementation is a lot hairier than you might think, but I've got it mostly working now. I've been meaning to post an answer to your StackOverflow question, but I wanted to be sure that the implementation was complete and as bug-free as possible. You can find the code here: https://github.com/MetaLang/phobos/commit/6c5fa291a957f4050910064d1fa44a86ff92e760

Basically, you just do `mixin(forwardToMember!(b, "p1", "p2"));` inside your wrapper class and it will automatically declare the correct methods/properties/aliases for you. Let me know if it works for your usecase and I'll post it to StackOverflow as well.
October 19, 2015
On Saturday, 17 October 2015 at 15:31:00 UTC, Nikolay wrote:
> I asked on SO question about opDispatch and compile time parameters: http://stackoverflow.com/questions/32998781/opdispatch-and-compile-time-parameters
> [...]
> Is it good idea for opDispatch improvement or may there is some other approach?

I must have my answer not too long after you made this thread, but there is another approach:
(copied from SO)

You need to use the eponymous template pattern, and have an opDispatch function with your compile-time parameters inside an outer opDispatch template that takes the regular opDispatch string parameter. You can also have multiple inner opDispatch functions (and fields) that follow regular overload rules.


    import std.stdio;

    struct Foo {

        public template opDispatch(string name) {

            public string opDispatch() {
                return name;
            }

            public T opDispatch(T)() {
               return T.init;
            }

            public string opDispatch(T)(string s) {
                return name ~ ' ' ~ T.stringof ~ ' ' ~ s;
            }
        }
    }

    void main()
    {
        Foo foo;
        writeln( foo.bar );
        writeln( foo.baz!int );
        writeln( foo.foo!Foo("foo") );
    }

Produces the output:

    bar
    0
    foo Foo foo

DPaste link: http://dpaste.dzfl.pl/6e5cfca8b702


I haven't fully explored the limitations of this approach, but it does work for simple cases.

October 19, 2015
D template system is very powerful.  This is more generic solution:

import std.stdio;
class B {
    auto p1(T)(T arg) { writeln( "p1: ", arg ); }
    auto p2(T, int C)(T s) { writeln( "p2: ", s, " / ", C); }
}
class C(T) {
    T b = new T;
    template opDispatch(string s) {
        template opDispatch(TARGS...) {
            auto opDispatch(ARGS...)(ARGS args) {
                static if(TARGS.length) return mixin("b." ~ s ~ "!TARGS(args)");
                else return mixin("b." ~ s ~ "(args)");
            }
        }
    }
}

void main() {
    auto b = new C!(B)();
    b.p1("abc");
    b.p2!(int, 10)(5);
}

http://dpaste.dzfl.pl/791c65d0e4ee
October 19, 2015
On Monday, 19 October 2015 at 08:41:46 UTC, Jack Applegame wrote:
> D template system is very powerful.  This is more generic solution:
>
> http://dpaste.dzfl.pl/791c65d0e4ee

Wow!

I can't believe that it is possible and there is so straightforward way. You should post this answer to SO

Thanks!

October 19, 2015
On 10/19/2015 01:50 PM, Nikolay wrote:
> On Monday, 19 October 2015 at 08:41:46 UTC, Jack Applegame wrote:
>> D template system is very powerful.  This is more generic solution:
>>
>> http://dpaste.dzfl.pl/791c65d0e4ee
>
> Wow!
>
> I can't believe that it is possible and there is so straightforward way.
> You should post this answer to SO
>
> Thanks!

It is amazing indeed. We should make this a standard library artifact.

Tangentially related: since when we allow field initialization with new? I was surprised to see that this works:

struct A {
	int[] x = new int[10];
}

void main() {
	import std.stdio;
	A a;
	writeln(a.x);
}

After all that talk about default constructors that don't do anything, it's ironic I didn't know about this language change :o).


Andrei

October 19, 2015
On Monday, 19 October 2015 at 18:16:15 UTC, Andrei Alexandrescu wrote:
> Tangentially related: since when we allow field initialization with new? I was surprised to see that this works:

Since CTFE started supporting it... this might actually be an unintentional feature.

Since the initializer is in a static context, the right hand side gets CTFE'd, which means that actually points to an array in the data segment... the *same* array in the data segment for all initializations (the pointer is just blitted over with the rest of init), which might be a bit surprising.

I've seen a lot of people do this with classes not realizing it makes a static instance!

October 19, 2015
On Monday, 19 October 2015 at 18:26:45 UTC, Adam D. Ruppe wrote:
> On Monday, 19 October 2015 at 18:16:15 UTC, Andrei Alexandrescu wrote:
>> Tangentially related: since when we allow field initialization with new? I was surprised to see that this works:
>
> Since CTFE started supporting it... this might actually be an unintentional feature.
>
> Since the initializer is in a static context, the right hand side gets CTFE'd, which means that actually points to an array in the data segment... the *same* array in the data segment for all initializations (the pointer is just blitted over with the rest of init), which might be a bit surprising.
>
> I've seen a lot of people do this with classes not realizing it makes a static instance!

Yeah. It makes sense when you're dealing with an immutable object/arrays (and possibly const, assuming that it wasn't initialized with a mutable variable that was directly initialized via new), but it really makes no sense for mutable objects/arrays - not unless you have some weird case where you want each instance of your object to be able to share that member variable initially and then possibly stop sharing later. But given the high probability that someone is going to do this and shoot themselves in the foot, I think that we'd be a lot better off if we disallowed it.

- Jonathan M Davis
October 19, 2015
On Monday, 19 October 2015 at 17:50:02 UTC, Nikolay wrote:
> On Monday, 19 October 2015 at 08:41:46 UTC, Jack Applegame wrote:
>> D template system is very powerful.  This is more generic solution:
>>
>> http://dpaste.dzfl.pl/791c65d0e4ee
>
> Wow!
>
> I can't believe that it is possible and there is so straightforward way. You should post this answer to SO
>
> Thanks!

Done


October 19, 2015
On 10/19/2015 02:26 PM, Adam D. Ruppe wrote:
> On Monday, 19 October 2015 at 18:16:15 UTC, Andrei Alexandrescu wrote:
>> Tangentially related: since when we allow field initialization with
>> new? I was surprised to see that this works:
>
> Since CTFE started supporting it... this might actually be an
> unintentional feature.
>
> Since the initializer is in a static context, the right hand side gets
> CTFE'd, which means that actually points to an array in the data
> segment... the *same* array in the data segment for all initializations
> (the pointer is just blitted over with the rest of init), which might be
> a bit surprising.
>
> I've seen a lot of people do this with classes not realizing it makes a
> static instance!

This works too:


struct A {
    int[] x = new int[10];
}

void main() {
    import std.stdio;
    A a;
    a.x[1] = 42;
    writeln(a.x);
}

Looks like a bona fide runtime array to me.


Andrei
« First   ‹ Prev
1 2 3