www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Cannot dup an associative array but why?

reply Jean-Louis Leroy <jl leroy.nyc> writes:
Is there something special about ClassInfo that confuses? Look at 
this example:

struct Foo
{

}

class Bar
{
}

void main()
{
   Foo*[Bar] a;
   auto aa = a.dup; // OK
   Foo*[ClassInfo] b; // Error: static assert  "cannot call 
Foo*[TypeInfo_Class].dup because Foo* is not copyable"
   auto bb = b.dup; // instantiated from here: 
dup!(Foo*[TypeInfo_Class], TypeInfo_Class, Foo*)}
}

'Foo*' is not copyable? Except that it is if the key is something 
else than ClassInfo? ClassInfo and Bar are both reference types 
though...
Jul 10
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 07/10/2017 11:46 AM, Jean-Louis Leroy wrote:
 Is there something special about ClassInfo that confuses? Look at this
 example:

 struct Foo
 {

 }

 class Bar
 {
 }

 void main()
 {
   Foo*[Bar] a;
   auto aa = a.dup; // OK
   Foo*[ClassInfo] b; // Error: static assert  "cannot call
 Foo*[TypeInfo_Class].dup because Foo* is not copyable"
I think you're hitting the same TypeInfo.init issue again. :/ This is the assert that fails inside object.dup: static assert(is(typeof({ V v = aa[K.init]; })), "cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable"); Jean-Louis, a little more patience please. :) Hopefully this will be resolved with 2.075, which you should be able to test yourself already. (?) 2.075 is in its fourth beta release. Ali
Jul 10
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Monday, 10 July 2017 at 19:11:37 UTC, Ali Çehreli wrote:
 On 07/10/2017 11:46 AM, Jean-Louis Leroy wrote:
 Is there something special about ClassInfo that confuses?
Look at this
 example:

 struct Foo
 {

 }

 class Bar
 {
 }

 void main()
 {
   Foo*[Bar] a;
   auto aa = a.dup; // OK
   Foo*[ClassInfo] b; // Error: static assert  "cannot call
 Foo*[TypeInfo_Class].dup because Foo* is not copyable"
I think you're hitting the same TypeInfo.init issue again. :/ This is the assert that fails inside object.dup: static assert(is(typeof({ V v = aa[K.init]; })), "cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable"); Jean-Louis, a little more patience please. :) Hopefully this will be resolved with 2.075, which you should be able to test yourself already. (?) 2.075 is in its fourth beta release. Ali
Howdy Ali ;-) Aaaah...those rough edges you were talking about at CppNow? FYI, having a lot of fun. See https://github.com/jll63/meth.d/blob/experiments/source/meth/examples/adventure.d At the time being, I'm hijacking ClassInfo.deallocator. I hope it will live through the next iteration of D.
Jul 10
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 07/10/2017 04:24 PM, Jean-Louis Leroy wrote:

 FYI, having a lot of fun. See
 
https://github.com/jll63/meth.d/blob/experiments/source/meth/examples/adventure.d I'm glad you're trying out multi-methods with D: https://github.com/jll63/meth.d/tree/experiments That's some serious code you've written there and you must be happy that 'virtual' is not a keyword in D. ;) Maybe others can come up with ideas on a better syntax. Just to get the conversation going and without thinking it through, how about something like the following? struct Virtual(Args...) { // ... } Virtual("t", "d", "w") string fight(Character t, Dragon d, Hands w) { return "you just killed a dragon with your bare hands. Incredible isn't it?"; } Then, something like the following which would parse the module to do its magic: mixin ProcessMethods(); // Can include 'static this()' for runtime initialization if necessary Again though, this is just a thought about making the syntax more fluent. More for the others to think about it for me. :) Ali
Jul 11
next sibling parent Jean-Louis Leroy <jl leroy.nyc> writes:
On Tuesday, 11 July 2017 at 17:20:33 UTC, Ali Çehreli wrote:

 That's some serious code you've written there and you must be 
 happy that 'virtual' is not a keyword in D. ;)
Thanks. Haha I would have used virtual_ like I did in C++ ;-)
 Maybe others can come up with ideas on a better syntax.
When it is presentable (I'm almost there) I plan to ask a review. I would welcome suggestions about the syntax - which is not too bad as it is now, I have been happily surprised with what is feasible. It even supports overloading methods. The thing that annoys me most is having to pass a string to 'method'. And attributes are not allowed on arguments. I wish I would make something like this work: mixin method!(fight, string, virtual!Character, virtual!Creature, virtual!Device); // or: mixin method!(fight, string, virtual Character, virtual Creature, virtual Device); // even better mixin method!(fight, function string( virtual Character, virtual Creature, virtual Device)); // and if there is a catch-all implementation: mixin method!(fight, function string( virtual Character, virtual Creature, virtual Device) { // body } I tried to get inspiration from Yes and No, considered using opDispatch, but I haven't found a way yet.
 Just to get the conversation going and without thinking it 
 through, how about something like the following?

 struct Virtual(Args...) {
     // ...
 }

  Virtual("t", "d", "w")
 string fight(Character t, Dragon d, Hands w) {
     return "you just killed a dragon with your bare hands. 
 Incredible isn't it?";
 }
The 'virtual' qualifier applies to the arguments in the method declaration, not the specializations. Also, I prefer to keep the qualifiers stuck to the argument. It's clearer. Interesting idea though.
 Then, something like the following which would parse the module 
 to do its magic:

 mixin ProcessMethods();
Very interesting. I don't like the repetition of 'mixin' in front of each 'method' and 'implementation'. Hmmm...if ProcessMethods() can find Virtual(...) functions can't it find functions that have virtual! parameters?
Jul 11
prev sibling parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Tuesday, 11 July 2017 at 17:20:33 UTC, Ali Çehreli wrote:

  Virtual("t", "d", "w")
 string fight(Character t, Dragon d, Hands w) {
     return "you just killed a dragon with your bare hands. 
 Incredible isn't it?";
 [...]
 mixin ProcessMethods();
Great suggestion! I think this could work: string fight(virtual!Character, virtual!Creature, virtual!Device); // declares method // define implemention: string fight(Character t, Dragon d, Hands w); mixin ProcessMethods(); How do you find the current module inside ProcessMethods? There's a problem with the catch-all method though: string fight(Character a, Creature b, Device c) { } This won't work because string fight(Character a, Creature b, Device c) is the method itself - it's generated by the library. We'll have to come up with a special syntax for it. J-L
Jul 11
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 07/11/2017 01:25 PM, Jean-Louis Leroy wrote:
 On Tuesday, 11 July 2017 at 17:20:33 UTC, Ali Çehreli wrote:

  Virtual("t", "d", "w")
 string fight(Character t, Dragon d, Hands w) {
     return "you just killed a dragon with your bare hands. Incredible
 isn't it?";
 [...]
 mixin ProcessMethods();
Great suggestion! I think this could work: string fight(virtual!Character, virtual!Creature, virtual!Device); // declares method // define implemention: string fight(Character t, Dragon d, Hands w); mixin ProcessMethods(); How do you find the current module inside ProcessMethods?
Default template and function arguments are resolved at instantiation site, which means __MODULE__ would resolve automatically to the caller's module. For example, if you have this module: ------------------ module a; mixin template ProcessMethods(string mod = __MODULE__) { enum s = "Working with " ~ mod; } ------------------ The user can simply mix it in: ------------------ module deneme; import a; mixin ProcessMethods; void main() { pragma(msg, s); } ------------------ And the string has the user's module 'deneme': Working with deneme Ali
Jul 11
parent Jean-Louis Leroy <jl leroy.nyc> writes:
On Tuesday, 11 July 2017 at 21:23:28 UTC, Ali Çehreli wrote:
 Default template and function arguments are resolved at 
 instantiation site, which means __MODULE__ would resolve 
 automatically to the caller's module. For example, if you have 
 this module:
__MODULE__ is a string so I cannot pass it to __traits(allMembers). I worked around it via a string mixin that creates an alias for the module: template RegisterMethods() { import std.array; mixin("alias MODULE = " ~ __MODULE__ ~ ";"); auto RegisterMethods() { string[] s; foreach (m; __traits(allMembers, MODULE)) { // do stuff } return join(s, ""); } } mixin(RegisterMethods); I wonder if there is a better way. Also, I am using the outer string mixin (as opposed to a plain mixin) because I will need to produce a series of aliases: mixin(RegisterMethods); // injects: // alias add = Method!("add", Matrix, virtual!Matrix, virtual!Matrix).dispatcher // alias add = Method!("add", Matrix, virtual!Matrix, virtual!Matrix).discriminator; // alias kick = Method!("kick", Animal).dispatcher // alias kick = Method!("kick", Animal).discriminator // etc The only way I can see is with a string mixin. I thought about the new syntax since yesterday, and hit some problems and some solutions. At this point maybe we should continue that discussion elsewhere than the Learn forum...
Jul 12