Re: Any way to override base type with dervived in derived type
On Friday, 25 May 2018 at 01:42:48 UTC, Basile B. wrote: On Friday, 25 May 2018 at 01:17:45 UTC, IntegratedDimensions wrote: On Friday, 25 May 2018 at 01:02:00 UTC, Basile B. wrote: On Friday, 25 May 2018 at 00:15:39 UTC, IntegratedDimensions wrote: On Thursday, 24 May 2018 at 23:31:50 UTC, Alex wrote: On Thursday, 24 May 2018 at 20:24:32 UTC, IntegratedDimensions wrote: class T; class TT : T; interface I { @property T t(); } abstract class A { T _t; @property T t() { return _t; } } class C : A { // Stuff below uses t as TT but compiler, of course, treats t as T ... } The issue is that I programmed the class C with a variable that directly was based off TT, I later subderived T from TT and exposed it in I. (TT was refactored in to T and not T) As as a side note: I can hardly follow this, as you don't show, where you use the interface I. However, especially if TT was refactored in such a way, that is a set difference of T and not T, why you choose to derive from T instead of to contain T? It really should be obvious that A was meant to derive from I. This is just standard oop. Simply leaving off : I should not be a deal breaker because it would not change the whole problem from black to white or vice versa. T is a member to be included. You can only derive from one class. C can't derive from both A and T and even if it did, it would mean something else. https://en.wikipedia.org/wiki/Composition_over_inheritance http://wiki.c2.com/?CompositionInsteadOfInheritance Well, can imagine useful cases though... This is not a composition pattern. This is a parallel inherentence pattern. TT : T = T || | vv v C : A : I TT is used with C and T with I. When C changes to C', TT : T changes to TT' : T All functions that use TT in C are forced to use it as if it were of type T rather than TT which requires a bunch of casts. This is generally a violation of type logic. There is nothing in that prevents t from being something like TTT which has no direct relation to TT. But the programming logic of the code enforces t to be of type TT in C *always*. So I don't know why I would have to use casting all the time. It would be nice if there where a simple logical way to enforce a design pattern in the type system knowing that it is enforced at runtime. This makes cleaner code, nothing else. But all the code in C assumes t is of type TT but now due to the interface it looks like a T, even though internally it is actually a TT. What I'd like to do is class C : A { private override @property TT t() { return cast(TT)(_t); } // null check if necessary // Stuff below uses t which is now a TT ... } or whatever. This is simply so I don't have to rename or cast all my uses of t in C to type TT. I'm pretty much guaranteed that in C, t will be type TT due to the design(C goes with TT like bread with butter). So, it would be nice if somehow I could inform the type system that in C, t is always of type TT and so treat it as such rather than forcing me to explicitly cast for every use. Again, I could rename things to avoid the same name usage but in this case it is not necessary because of the design. Is there any semantics that can get me around having to rename? Maybe, you are looking for Curiously Recurring Template Pattern? ´´´ interface I(P) { @property P t(); } abstract class T(P) : I!P { P _p; @property P t() { return _p; } } class TT : T!TT { } void main() { auto tt = new TT(); static assert(is(typeof(tt.t) == TT)); } ´´´ No, I am trying to keep parallel derived types consistently connected. If A is derived from B and C from D and B uses D then A uses C. Consistency cannot be guaranteed by the type system at compile time because A is typed to use C, I want to restrict it further to D. You must put a template parameter in the interface and specialize the class that implements the interface. ``` module runnable; class T{} class TT : T{} interface I(N) { @property N t(); } abstract class A(N) : I!N { N _t; @property N t() { return _t; } } class C1 : A!T{} class C2 : A!TT{} void main(string[] args) { import std.traits; static assert(is(ReturnType!(C1.t) == T)); static assert(is(ReturnType!(C2.t) == TT)); } module runnable; class T{} class TT : T{} interface I(N) { @property N t(); } abstract class A(N) : I!N { N _t; @property N t() { return _t; } } class C1 : A!T{} class C2 : A!TT{} void main(string[] args) { import std.traits; static assert(is(ReturnType!(C1.t) == T)); static assert(is(ReturnType!(C2.t) == TT)); } ``` but obviously this won't work if you want to derive C1 or C2... or if there 100 fields. This isn't a proper solution. The whole issue is not outside of C but inside Hypothetically class C : A { @property TT : T t() { return _t; } // t can be used directly as TT rather than havin
Re: Any way to override base type with dervived in derived type
On Friday, 25 May 2018 at 01:17:45 UTC, IntegratedDimensions wrote: On Friday, 25 May 2018 at 01:02:00 UTC, Basile B. wrote: On Friday, 25 May 2018 at 00:15:39 UTC, IntegratedDimensions wrote: On Thursday, 24 May 2018 at 23:31:50 UTC, Alex wrote: On Thursday, 24 May 2018 at 20:24:32 UTC, IntegratedDimensions wrote: class T; class TT : T; interface I { @property T t(); } abstract class A { T _t; @property T t() { return _t; } } class C : A { // Stuff below uses t as TT but compiler, of course, treats t as T ... } The issue is that I programmed the class C with a variable that directly was based off TT, I later subderived T from TT and exposed it in I. (TT was refactored in to T and not T) As as a side note: I can hardly follow this, as you don't show, where you use the interface I. However, especially if TT was refactored in such a way, that is a set difference of T and not T, why you choose to derive from T instead of to contain T? It really should be obvious that A was meant to derive from I. This is just standard oop. Simply leaving off : I should not be a deal breaker because it would not change the whole problem from black to white or vice versa. T is a member to be included. You can only derive from one class. C can't derive from both A and T and even if it did, it would mean something else. https://en.wikipedia.org/wiki/Composition_over_inheritance http://wiki.c2.com/?CompositionInsteadOfInheritance Well, can imagine useful cases though... This is not a composition pattern. This is a parallel inherentence pattern. TT : T = T || | vv v C : A : I TT is used with C and T with I. When C changes to C', TT : T changes to TT' : T All functions that use TT in C are forced to use it as if it were of type T rather than TT which requires a bunch of casts. This is generally a violation of type logic. There is nothing in that prevents t from being something like TTT which has no direct relation to TT. But the programming logic of the code enforces t to be of type TT in C *always*. So I don't know why I would have to use casting all the time. It would be nice if there where a simple logical way to enforce a design pattern in the type system knowing that it is enforced at runtime. This makes cleaner code, nothing else. But all the code in C assumes t is of type TT but now due to the interface it looks like a T, even though internally it is actually a TT. What I'd like to do is class C : A { private override @property TT t() { return cast(TT)(_t); } // null check if necessary // Stuff below uses t which is now a TT ... } or whatever. This is simply so I don't have to rename or cast all my uses of t in C to type TT. I'm pretty much guaranteed that in C, t will be type TT due to the design(C goes with TT like bread with butter). So, it would be nice if somehow I could inform the type system that in C, t is always of type TT and so treat it as such rather than forcing me to explicitly cast for every use. Again, I could rename things to avoid the same name usage but in this case it is not necessary because of the design. Is there any semantics that can get me around having to rename? Maybe, you are looking for Curiously Recurring Template Pattern? ´´´ interface I(P) { @property P t(); } abstract class T(P) : I!P { P _p; @property P t() { return _p; } } class TT : T!TT { } void main() { auto tt = new TT(); static assert(is(typeof(tt.t) == TT)); } ´´´ No, I am trying to keep parallel derived types consistently connected. If A is derived from B and C from D and B uses D then A uses C. Consistency cannot be guaranteed by the type system at compile time because A is typed to use C, I want to restrict it further to D. You must put a template parameter in the interface and specialize the class that implements the interface. ``` module runnable; class T{} class TT : T{} interface I(N) { @property N t(); } abstract class A(N) : I!N { N _t; @property N t() { return _t; } } class C1 : A!T{} class C2 : A!TT{} void main(string[] args) { import std.traits; static assert(is(ReturnType!(C1.t) == T)); static assert(is(ReturnType!(C2.t) == TT)); } module runnable; class T{} class TT : T{} interface I(N) { @property N t(); } abstract class A(N) : I!N { N _t; @property N t() { return _t; } } class C1 : A!T{} class C2 : A!TT{} void main(string[] args) { import std.traits; static assert(is(ReturnType!(C1.t) == T)); static assert(is(ReturnType!(C2.t) == TT)); } ``` but obviously this won't work if you want to derive C1 or C2... or if there 100 fields. This isn't a proper solution. The whole issue is not outside of C but inside Hypothetically class C : A { @property TT : T t() { return _t; } // t can be used directly as TT rather than having to do (cast(TT)t) everywhere t is used. } would solve t
Re: Any way to override base type with dervived in derived type
On Friday, 25 May 2018 at 01:02:00 UTC, Basile B. wrote: On Friday, 25 May 2018 at 00:15:39 UTC, IntegratedDimensions wrote: On Thursday, 24 May 2018 at 23:31:50 UTC, Alex wrote: On Thursday, 24 May 2018 at 20:24:32 UTC, IntegratedDimensions wrote: class T; class TT : T; interface I { @property T t(); } abstract class A { T _t; @property T t() { return _t; } } class C : A { // Stuff below uses t as TT but compiler, of course, treats t as T ... } The issue is that I programmed the class C with a variable that directly was based off TT, I later subderived T from TT and exposed it in I. (TT was refactored in to T and not T) As as a side note: I can hardly follow this, as you don't show, where you use the interface I. However, especially if TT was refactored in such a way, that is a set difference of T and not T, why you choose to derive from T instead of to contain T? It really should be obvious that A was meant to derive from I. This is just standard oop. Simply leaving off : I should not be a deal breaker because it would not change the whole problem from black to white or vice versa. T is a member to be included. You can only derive from one class. C can't derive from both A and T and even if it did, it would mean something else. https://en.wikipedia.org/wiki/Composition_over_inheritance http://wiki.c2.com/?CompositionInsteadOfInheritance Well, can imagine useful cases though... This is not a composition pattern. This is a parallel inherentence pattern. TT : T = T || | vv v C : A : I TT is used with C and T with I. When C changes to C', TT : T changes to TT' : T All functions that use TT in C are forced to use it as if it were of type T rather than TT which requires a bunch of casts. This is generally a violation of type logic. There is nothing in that prevents t from being something like TTT which has no direct relation to TT. But the programming logic of the code enforces t to be of type TT in C *always*. So I don't know why I would have to use casting all the time. It would be nice if there where a simple logical way to enforce a design pattern in the type system knowing that it is enforced at runtime. This makes cleaner code, nothing else. But all the code in C assumes t is of type TT but now due to the interface it looks like a T, even though internally it is actually a TT. What I'd like to do is class C : A { private override @property TT t() { return cast(TT)(_t); } // null check if necessary // Stuff below uses t which is now a TT ... } or whatever. This is simply so I don't have to rename or cast all my uses of t in C to type TT. I'm pretty much guaranteed that in C, t will be type TT due to the design(C goes with TT like bread with butter). So, it would be nice if somehow I could inform the type system that in C, t is always of type TT and so treat it as such rather than forcing me to explicitly cast for every use. Again, I could rename things to avoid the same name usage but in this case it is not necessary because of the design. Is there any semantics that can get me around having to rename? Maybe, you are looking for Curiously Recurring Template Pattern? ´´´ interface I(P) { @property P t(); } abstract class T(P) : I!P { P _p; @property P t() { return _p; } } class TT : T!TT { } void main() { auto tt = new TT(); static assert(is(typeof(tt.t) == TT)); } ´´´ No, I am trying to keep parallel derived types consistently connected. If A is derived from B and C from D and B uses D then A uses C. Consistency cannot be guaranteed by the type system at compile time because A is typed to use C, I want to restrict it further to D. You must put a template parameter in the interface and specialize the class that implements the interface. ``` module runnable; class T{} class TT : T{} interface I(N) { @property N t(); } abstract class A(N) : I!N { N _t; @property N t() { return _t; } } class C1 : A!T{} class C2 : A!TT{} void main(string[] args) { import std.traits; static assert(is(ReturnType!(C1.t) == T)); static assert(is(ReturnType!(C2.t) == TT)); } module runnable; class T{} class TT : T{} interface I(N) { @property N t(); } abstract class A(N) : I!N { N _t; @property N t() { return _t; } } class C1 : A!T{} class C2 : A!TT{} void main(string[] args) { import std.traits; static assert(is(ReturnType!(C1.t) == T)); static assert(is(ReturnType!(C2.t) == TT)); } ``` but obviously this won't work if you want to derive C1 or C2... or if there 100 fields. This isn't a proper solution. The whole issue is not outside of C but inside Hypothetically class C : A { @property TT : T t() { return _t; } // t can be used directly as TT rather than having to do (cast(TT)t) everywhere t is used. } would solve the problem and it would scale. The way it would work is that inside C
Re: Any way to override base type with dervived in derived type
On Friday, 25 May 2018 at 00:15:39 UTC, IntegratedDimensions wrote: On Thursday, 24 May 2018 at 23:31:50 UTC, Alex wrote: On Thursday, 24 May 2018 at 20:24:32 UTC, IntegratedDimensions wrote: class T; class TT : T; interface I { @property T t(); } abstract class A { T _t; @property T t() { return _t; } } class C : A { // Stuff below uses t as TT but compiler, of course, treats t as T ... } The issue is that I programmed the class C with a variable that directly was based off TT, I later subderived T from TT and exposed it in I. (TT was refactored in to T and not T) As as a side note: I can hardly follow this, as you don't show, where you use the interface I. However, especially if TT was refactored in such a way, that is a set difference of T and not T, why you choose to derive from T instead of to contain T? It really should be obvious that A was meant to derive from I. This is just standard oop. Simply leaving off : I should not be a deal breaker because it would not change the whole problem from black to white or vice versa. T is a member to be included. You can only derive from one class. C can't derive from both A and T and even if it did, it would mean something else. https://en.wikipedia.org/wiki/Composition_over_inheritance http://wiki.c2.com/?CompositionInsteadOfInheritance Well, can imagine useful cases though... This is not a composition pattern. This is a parallel inherentence pattern. TT : T = T || | vv v C : A : I TT is used with C and T with I. When C changes to C', TT : T changes to TT' : T All functions that use TT in C are forced to use it as if it were of type T rather than TT which requires a bunch of casts. This is generally a violation of type logic. There is nothing in that prevents t from being something like TTT which has no direct relation to TT. But the programming logic of the code enforces t to be of type TT in C *always*. So I don't know why I would have to use casting all the time. It would be nice if there where a simple logical way to enforce a design pattern in the type system knowing that it is enforced at runtime. This makes cleaner code, nothing else. But all the code in C assumes t is of type TT but now due to the interface it looks like a T, even though internally it is actually a TT. What I'd like to do is class C : A { private override @property TT t() { return cast(TT)(_t); } // null check if necessary // Stuff below uses t which is now a TT ... } or whatever. This is simply so I don't have to rename or cast all my uses of t in C to type TT. I'm pretty much guaranteed that in C, t will be type TT due to the design(C goes with TT like bread with butter). So, it would be nice if somehow I could inform the type system that in C, t is always of type TT and so treat it as such rather than forcing me to explicitly cast for every use. Again, I could rename things to avoid the same name usage but in this case it is not necessary because of the design. Is there any semantics that can get me around having to rename? Maybe, you are looking for Curiously Recurring Template Pattern? ´´´ interface I(P) { @property P t(); } abstract class T(P) : I!P { P _p; @property P t() { return _p; } } class TT : T!TT { } void main() { auto tt = new TT(); static assert(is(typeof(tt.t) == TT)); } ´´´ No, I am trying to keep parallel derived types consistently connected. If A is derived from B and C from D and B uses D then A uses C. Consistency cannot be guaranteed by the type system at compile time because A is typed to use C, I want to restrict it further to D. You must put a template parameter in the interface and specialize the class that implements the interface. ``` module runnable; class T{} class TT : T{} interface I(N) { @property N t(); } abstract class A(N) : I!N { N _t; @property N t() { return _t; } } class C1 : A!T{} class C2 : A!TT{} void main(string[] args) { import std.traits; static assert(is(ReturnType!(C1.t) == T)); static assert(is(ReturnType!(C2.t) == TT)); } module runnable; class T{} class TT : T{} interface I(N) { @property N t(); } abstract class A(N) : I!N { N _t; @property N t() { return _t; } } class C1 : A!T{} class C2 : A!TT{} void main(string[] args) { import std.traits; static assert(is(ReturnType!(C1.t) == T)); static assert(is(ReturnType!(C2.t) == TT)); } ``` but obviously this won't work if you want to derive C1 or C2...
Re: Any way to override base type with dervived in derived type
On Thursday, 24 May 2018 at 23:31:50 UTC, Alex wrote: On Thursday, 24 May 2018 at 20:24:32 UTC, IntegratedDimensions wrote: class T; class TT : T; interface I { @property T t(); } abstract class A { T _t; @property T t() { return _t; } } class C : A { // Stuff below uses t as TT but compiler, of course, treats t as T ... } The issue is that I programmed the class C with a variable that directly was based off TT, I later subderived T from TT and exposed it in I. (TT was refactored in to T and not T) As as a side note: I can hardly follow this, as you don't show, where you use the interface I. However, especially if TT was refactored in such a way, that is a set difference of T and not T, why you choose to derive from T instead of to contain T? It really should be obvious that A was meant to derive from I. This is just standard oop. Simply leaving off : I should not be a deal breaker because it would not change the whole problem from black to white or vice versa. T is a member to be included. You can only derive from one class. C can't derive from both A and T and even if it did, it would mean something else. https://en.wikipedia.org/wiki/Composition_over_inheritance http://wiki.c2.com/?CompositionInsteadOfInheritance Well, can imagine useful cases though... This is not a composition pattern. This is a parallel inherentence pattern. TT : T = T || | vv v C : A : I TT is used with C and T with I. When C changes to C', TT : T changes to TT' : T All functions that use TT in C are forced to use it as if it were of type T rather than TT which requires a bunch of casts. This is generally a violation of type logic. There is nothing in that prevents t from being something like TTT which has no direct relation to TT. But the programming logic of the code enforces t to be of type TT in C *always*. So I don't know why I would have to use casting all the time. It would be nice if there where a simple logical way to enforce a design pattern in the type system knowing that it is enforced at runtime. This makes cleaner code, nothing else. But all the code in C assumes t is of type TT but now due to the interface it looks like a T, even though internally it is actually a TT. What I'd like to do is class C : A { private override @property TT t() { return cast(TT)(_t); } // null check if necessary // Stuff below uses t which is now a TT ... } or whatever. This is simply so I don't have to rename or cast all my uses of t in C to type TT. I'm pretty much guaranteed that in C, t will be type TT due to the design(C goes with TT like bread with butter). So, it would be nice if somehow I could inform the type system that in C, t is always of type TT and so treat it as such rather than forcing me to explicitly cast for every use. Again, I could rename things to avoid the same name usage but in this case it is not necessary because of the design. Is there any semantics that can get me around having to rename? Maybe, you are looking for Curiously Recurring Template Pattern? ´´´ interface I(P) { @property P t(); } abstract class T(P) : I!P { P _p; @property P t() { return _p; } } class TT : T!TT { } void main() { auto tt = new TT(); static assert(is(typeof(tt.t) == TT)); } ´´´ No, I am trying to keep parallel derived types consistently connected. If A is derived from B and C from D and B uses D then A uses C. Consistency cannot be guaranteed by the type system at compile time because A is typed to use C, I want to restrict it further to D.
Re: Why char[] is not @nogc on this case
On Friday, May 25, 2018 00:09:28 SrMordred via Digitalmars-d-learn wrote: > On Friday, 25 May 2018 at 00:04:10 UTC, Adam D. Ruppe wrote: > > On Thursday, 24 May 2018 at 23:55:24 UTC, SrMordred wrote: > >> //Error: @nogc delegate onlineapp.main.__lambda1 cannot call > >> non-@nogc function std.range.chain!(char[], > >> char[]).chain.Result.front > >> > >> Why? > > > > phobos automatically decodes utf8 into dchars. This can throw a > > new utf exception. > > Oh its the utf8 decode thing. > I forgot about it. > I thought that it only decodes when using strings and dchars. It happens with any "narrow string" - i.e. any array of char or dchar. You can test for it with std.traits.isNarrowString, whose current implementation is: enum bool isNarrowString(T) = isSomeString!T && !is(T : const dchar[]); Basically, unless a range-based function goes out of its way to specialize for narrow strings and avoids any decoding (and whether that makes any sense depends on what the function does), it's going to treat any array of char or wchar as a range of dchar and will throw a UTFException on invalid Unicode. - Jonathan M Davis
Re: Why char[] is not @nogc on this case
Because arrays of char and wchar are treated as ranges of dchar. That part that I didnt know, thanks! :)
Re: Why char[] is not @nogc on this case
On Friday, 25 May 2018 at 00:04:10 UTC, Adam D. Ruppe wrote: On Thursday, 24 May 2018 at 23:55:24 UTC, SrMordred wrote: //Error: @nogc delegate onlineapp.main.__lambda1 cannot call non-@nogc function std.range.chain!(char[], char[]).chain.Result.front Why? phobos automatically decodes utf8 into dchars. This can throw a new utf exception. Oh its the utf8 decode thing. I forgot about it. I thought that it only decodes when using strings and dchars. Thanks!
Re: Why char[] is not @nogc on this case
On Thursday, May 24, 2018 23:55:24 SrMordred via Digitalmars-d-learn wrote: > int[] a; > int[] b; > > ()@nogc { > foreach(v ; chain( a,b ) ) printf("%d\n", v); > }(); > > //Ok, everything fine; > > char[] a; > char[] b; > > ()@nogc { > foreach(v ; chain( a,b ) ) printf("%c\n", v); > }(); > > //Error: @nogc delegate onlineapp.main.__lambda1 cannot call > non-@nogc function std.range.chain!(char[], > char[]).chain.Result.front > > Why? Because arrays of char and wchar are treated as ranges of dchar. std.primitives.range.front and popFront call std.utf.decode and stride respectively so that front returns dchar. decode (and possibly stride - I'd have to check) throw a UTFException on invalid Unicode, and that means that they allocate with the GC. If you want to avoid the auto-decoding, you have to use something like std.string.representation or std.utf.byCodeUnit to wrap the array of chars before passing them to any range-based functions. - Jonathan M Davis
Re: Why char[] is not @nogc on this case
On Thursday, 24 May 2018 at 23:55:24 UTC, SrMordred wrote: //Error: @nogc delegate onlineapp.main.__lambda1 cannot call non-@nogc function std.range.chain!(char[], char[]).chain.Result.front Why? phobos automatically decodes utf8 into dchars. This can throw a new utf exception.
Why char[] is not @nogc on this case
int[] a; int[] b; ()@nogc { foreach(v ; chain( a,b ) ) printf("%d\n", v); }(); //Ok, everything fine; char[] a; char[] b; ()@nogc { foreach(v ; chain( a,b ) ) printf("%c\n", v); }(); //Error: @nogc delegate onlineapp.main.__lambda1 cannot call non-@nogc function std.range.chain!(char[], char[]).chain.Result.front Why?
Re: Any way to override base type with dervived in derived type
On Thursday, 24 May 2018 at 20:24:32 UTC, IntegratedDimensions wrote: class T; class TT : T; interface I { @property T t(); } abstract class A { T _t; @property T t() { return _t; } } class C : A { // Stuff below uses t as TT but compiler, of course, treats t as T ... } The issue is that I programmed the class C with a variable that directly was based off TT, I later subderived T from TT and exposed it in I. (TT was refactored in to T and not T) As as a side note: I can hardly follow this, as you don't show, where you use the interface I. However, especially if TT was refactored in such a way, that is a set difference of T and not T, why you choose to derive from T instead of to contain T? https://en.wikipedia.org/wiki/Composition_over_inheritance http://wiki.c2.com/?CompositionInsteadOfInheritance Well, can imagine useful cases though... But all the code in C assumes t is of type TT but now due to the interface it looks like a T, even though internally it is actually a TT. What I'd like to do is class C : A { private override @property TT t() { return cast(TT)(_t); } // null check if necessary // Stuff below uses t which is now a TT ... } or whatever. This is simply so I don't have to rename or cast all my uses of t in C to type TT. I'm pretty much guaranteed that in C, t will be type TT due to the design(C goes with TT like bread with butter). So, it would be nice if somehow I could inform the type system that in C, t is always of type TT and so treat it as such rather than forcing me to explicitly cast for every use. Again, I could rename things to avoid the same name usage but in this case it is not necessary because of the design. Is there any semantics that can get me around having to rename? Maybe, you are looking for Curiously Recurring Template Pattern? ´´´ interface I(P) { @property P t(); } abstract class T(P) : I!P { P _p; @property P t() { return _p; } } class TT : T!TT { } void main() { auto tt = new TT(); static assert(is(typeof(tt.t) == TT)); } ´´´
Re: Assigning a method name to a variable and then calling it with an object
On Thursday, 24 May 2018 at 23:08:29 UTC, Basile B. wrote: On Thursday, 24 May 2018 at 23:03:21 UTC, aliak wrote: Hi, I was essentially trying to do this: struct S { void f() {} } auto f = S.f; // f becomes void function(S) ?? S s; f(s); Is something like that possible? Cheers, - Ali Sure: ``` import std.stdio; void main(string[] args) { struct S { void f() {"yeah possible".writeln;} } void delegate() f; f.funcptr = &S.f; S s; f.ptr = &s; s.f(); } ``` It's just that you have to learn the ABI of D delegates. There are two members: .funcptr (function) and .ptr (context, i.e the "this"). ahh, gracias!
Re: Assigning a method name to a variable and then calling it with an object
On Thursday, 24 May 2018 at 23:03:21 UTC, aliak wrote: Hi, I was essentially trying to do this: struct S { void f() {} } auto f = S.f; // f becomes void function(S) ?? S s; f(s); Is something like that possible? Cheers, - Ali Sure: ``` import std.stdio; void main(string[] args) { struct S { void f() {"yeah possible".writeln;} } void delegate() f; f.funcptr = &S.f; S s; f.ptr = &s; s.f(); } ``` It's just that you have to learn the ABI of D delegates. There are two members: .funcptr (function) and .ptr (context, i.e the "this").
Assigning a method name to a variable and then calling it with an object
Hi, I was essentially trying to do this: struct S { void f() {} } auto f = S.f; // f becomes void function(S) ?? S s; f(s); Is something like that possible? Cheers, - Ali
Stateful modules and extern(C)
I want to call some of my D code from Python. I'm annotating the pertinent functions with extern(C) export, as in module foo; extern(C) export int initialize() { return 42; } I compile with: dmd -fPIC -shared ./foo.d From the Python end, I can load the library using ctypes and the call works fine. The problem is, as soon as I have some state in my D module, as in: module foo; int call_count; extern(C) export int initialize() { ++call_count; return 42; } the call to initialize from python gives: AttributeError: ./foo.so: undefined symbol: initialize Can you share some tips/examples of non-trivial/stateful D modules that are successfully export(C)ed and maybe consumed with ctypes? Are there any specific attributes that I need to annotate my module globals with? Thank you! Arredondo.
Re: UFCS syntax I never saw before.
On Thursday, 24 May 2018 at 22:03:38 UTC, aliak wrote: It feels like the only difference between a no-arg function that is @property and one that is not is that the former could be invoked with optional parentheses and the latter should be illegal with parentheses. Edit: err... other way around!
Re: UFCS syntax I never saw before.
On Tuesday, 22 May 2018 at 14:33:20 UTC, Jonathan M Davis wrote: A free function with a single argument works just fine as a setter property. e.g. you could do something like void env(Tuple!(string, string)[] str) { // set environment variables } env = [tuple("foo", "bar")]; is perfectly legal. I question that there are many cases where such a function would be considered good design, but basically any case where it would make sense to have a function act like a global variable is currently allowed but would be disallowed if you couldn't have a setter property with only one argument. - Jonathan M Davis That can be attributed with @property if the developer intends for it to be used in that way, else should be illegal.
Re: UFCS syntax I never saw before.
On Tuesday, 22 May 2018 at 13:59:16 UTC, Steven Schveighoffer wrote: The derailed plan was to leave alone the ability to call no-arg functions without parentheses, but to REQUIRE @property to call an argument-taking function with the assignment style. See the DIP here: https://wiki.dlang.org/DIP23 Written by Walter and Andrei. I can't remember why it didn't happen. -Steve Aha. Thanks for the link! It feels like the only difference between a no-arg function that is @property and one that is not is that the former could be invoked with optional parentheses and the latter should be illegal with parentheses. Whereas an argument taking function marked as @property should probably allow read or write operations depending on whether or not it's invoked with an implicit first argument or not: @property int f(int) { ... } 1.f; // read op f = 1; // write op And to make parentheses illegal as well of course.
Any way to override base type with dervived in derived type
class T; class TT : T; interface I { @property T t(); } abstract class A { T _t; @property T t() { return _t; } } class C : A { // Stuff below uses t as TT but compiler, of course, treats t as T ... } The issue is that I programmed the class C with a variable that directly was based off TT, I later subderived T from TT and exposed it in I. (TT was refactored in to T and not T) But all the code in C assumes t is of type TT but now due to the interface it looks like a T, even though internally it is actually a TT. What I'd like to do is class C : A { private override @property TT t() { return cast(TT)(_t); } // null check if necessary // Stuff below uses t which is now a TT ... } or whatever. This is simply so I don't have to rename or cast all my uses of t in C to type TT. I'm pretty much guaranteed that in C, t will be type TT due to the design(C goes with TT like bread with butter). So, it would be nice if somehow I could inform the type system that in C, t is always of type TT and so treat it as such rather than forcing me to explicitly cast for every use. Again, I could rename things to avoid the same name usage but in this case it is not necessary because of the design. Is there any semantics that can get me around having to rename?
Re: try & catch / repeating code - DRY
On Thursday, May 24, 2018 19:39:07 Jacob Carlborg via Digitalmars-d-learn wrote: > On 2018-05-24 08:05, Robert M. Münch wrote: > > Hi, great! Thanks for the examples... BTW: Is there a place where such > > generic and fundamental examples are collected? > > Not as far as I know. > > >> void handleException1(alias dg)() > >> { > >> try dg(); > >> catch (Exception e) { /* handle exception */ } > >> } > >> > >> void handleException2(lazy void dg) > >> { > >> try dg(); > >> catch (Exception e) { /* handle exception */ } > >> } > >> > >> void handleException3(scope void delegate () dg) > >> { > >> try dg(); > >> catch (Exception e) { /* handle exception */ } > >> } > >> > >> void main() > >> { > >> handleException1!({ > >> writeln("asd"); > >> }); > >> > >> handleException1!(() => writeln("asd")); > >> > >> handleException2(writeln("asd")); > >> > >> handleException3({ > >> writeln("asd"); > >> }); > >> } > > > > What is exactly the difference between handleException1 and 3? > > With handleException1 the delegate needs to be passed as a template > argument, in the other case as a regular argument. I thought that the > lambda syntax, () => writeln("asd"), did not work as a regular argument, > but I checked now and it does. > > Passing it as a template argument might allow the compiler to inline it. > All range functions in Phobos are using template argument approach. With a template alias, it will accept pretty much any symbol (which would then normally be restricted by a template constraint so that it's a symbol which is usable in the target context), whereas an explicit delegate will only accept anything that implicitly converts to a delegate with that signature. What matches, I don't know, since I pretty much enver declare explicit delegates, though I don't find it surprising that a lambda works, since that's basically what a lambda is. But I expect that if you did something like pass a functor, it would work with the alias but wouldn't work with the delegate parameter. - Jonathan M Davis
Re: Conditionally set nothrow: for a block of code.
On 5/24/18 2:51 PM, Mike Franklin wrote: Given that the PR above is for object.d, I can't turn the entire object.d source file into a string and conditionally mix that in. Does anyone have a solution to this? My recommendation would have been the last one, but if that doesn't work, I don't think anything will that is... palatable. The only other avenue you *could* explore is importing a file as a string and mixing the whole thing in (prepending "nothrow:" at the top). Other than that, I think it's on to DIP territory. -Steve
Conditionally set nothrow: for a block of code.
I'm trying to find a way to declare a block of code `nothrow:` when compiling with -betterC, but not `nothrow` when not compiling with -betterC. The solution is needed for this PR: https://github.com/dlang/druntime/pull/2184/files#r188627707 Attempt #1 -- void test() { } version(D_BetterC) { nothrow: } extern(C) void main() { test(); // This should throw an error in -betterC because `main` is // `nothrow` but `test` isn't. It doesn't work } Attempt #2 -- version(D_BetterC) { enum isNoThrow = true; } else { enum isNoThrow = false; } void test() { } static if (isNoThrow) { nothrow: } extern(C) void main() { test(); // This should throw an error in -betterC because `main` is // `nothrow` but `test` isn't. It doesn't work } Attempt #3 -- version(D_BetterC) { enum nothrowValue = "nothrow:"; } else { enum nothrowValue = ""; } void test() { } mixin(nothrowValue); extern(C) void main() { test(); // This should throw an error in -betterC because `main` is // `nothrow` but `test` isn't. It doesn't work } Given that the PR above is for object.d, I can't turn the entire object.d source file into a string and conditionally mix that in. Does anyone have a solution to this? Thanks, Mike
Re: Translate C/C++ patern: return a pointer
On 2018-05-24 11:10, biocyberman wrote: Thanks for the hints. `Read` in C++ and D are both classes. And the function is inside the class definition itself. In that case specifying the type as `Read` is the correct thing to do. Note that `new` always allocates on the heap and returns a pointer or reference type. -- /Jacob Carlborg
Re: try & catch / repeating code - DRY
On 2018-05-24 08:05, Robert M. Münch wrote: Hi, great! Thanks for the examples... BTW: Is there a place where such generic and fundamental examples are collected? Not as far as I know. void handleException1(alias dg)() { try dg(); catch (Exception e) { /* handle exception */ } } void handleException2(lazy void dg) { try dg(); catch (Exception e) { /* handle exception */ } } void handleException3(scope void delegate () dg) { try dg(); catch (Exception e) { /* handle exception */ } } void main() { handleException1!({ writeln("asd"); }); handleException1!(() => writeln("asd")); handleException2(writeln("asd")); handleException3({ writeln("asd"); }); } What is exactly the difference between handleException1 and 3? With handleException1 the delegate needs to be passed as a template argument, in the other case as a regular argument. I thought that the lambda syntax, () => writeln("asd"), did not work as a regular argument, but I checked now and it does. Passing it as a template argument might allow the compiler to inline it. All range functions in Phobos are using template argument approach. -- /Jacob Carlborg
Re: return type of std.algorithm.mutation.reverse changed for good?
On Thursday, 24 May 2018 at 12:34:38 UTC, Steven Schveighoffer wrote: On 5/24/18 8:08 AM, rikki cattermole wrote: On 25/05/2018 12:06 AM, biocyberman wrote: I am testing with DMD 2.078.2 locally. This tiny snippet works on dlang's online editor: https://run.dlang.io/is/nb4IV4 But it does not work on my local dmd. import std.algorithm.mutation; import std.stdio; char[] arr = "hello\U00010143\u0100\U00010143".dup; writeln(arr.reverse); Error: template std.stdio.writeln cannot deduce function from argument types !()(void) The document says reverse returns a range: https://dlang.org/phobos/std_algorithm_mutation.html#reverse https://docarchives.dlang.io/v2.078.0/phobos/std_algorithm_mutation.html#reverse This doesn't quite tell the whole story. An array used to have a .reverse property that the compiler implemented, which returned the array after reversing it. So in history, this actually worked without std.algorithm. You get a nice history of what happens using "all dmd versions" on run.dlang.io. If you remove the "mutation" part from the import, you get: Up to 2.071.2: Success with output: 𐅃Ā𐅃olleh 2.072.2 to 2.074.1: Success with output: - onlineapp.d(6): Deprecation: use std.algorithm.reverse instead of .reverse property 𐅃Ā𐅃olleh - 2.075.1: Failure with output: - onlineapp.d(6): Error: template std.stdio.writeln cannot deduce function from argument types !()(void), candidates are: /path/to/dmd.linux/dmd2/linux/bin64/../../src/phobos/std/stdio.d(3553): std.stdio.writeln(T...)(T args) - 2.076.1 to 2.077.1: Failure with output: - onlineapp.d(6): Error: template std.stdio.writeln cannot deduce function from argument types !()(void), candidates are: /path/to/dmd.linux/dmd2/linux/bin64/../../src/phobos/std/stdio.d(3571): std.stdio.writeln(T...)(T args) - 2.078.1: Failure with output: - onlineapp.d(6): Error: template std.stdio.writeln cannot deduce function from argument types !()(void), candidates are: /path/to/dmd.linux/dmd2/linux/bin64/../../src/phobos/std/stdio.d(3657): std.stdio.writeln(T...)(T args) - Since 2.079.0: Success with output: 𐅃Ā𐅃olleh -Steve @Rikki and Steve: Many thanks for the good tips. I upgraded to dmd.2.080.0 now, but the server seems to be very slow. It's another story anyway. % ./install.sh dmd !9767 Downloading and unpacking http://downloads.dlang.org/releases/2.x/2.080.0/dmd.2.080.0.linux.tar.xz curl: (28) Operation too slow. Less than 1024 bytes/sec transferred the last 30 seconds Failed to download 'http://downloads.dlang.org/releases/2.x/2.080.0/dmd.2.080.0.linux.tar.xz'
Re: return type of std.algorithm.mutation.reverse changed for good?
On 5/24/18 8:08 AM, rikki cattermole wrote: On 25/05/2018 12:06 AM, biocyberman wrote: I am testing with DMD 2.078.2 locally. This tiny snippet works on dlang's online editor: https://run.dlang.io/is/nb4IV4 But it does not work on my local dmd. import std.algorithm.mutation; import std.stdio; char[] arr = "hello\U00010143\u0100\U00010143".dup; writeln(arr.reverse); Error: template std.stdio.writeln cannot deduce function from argument types !()(void) The document says reverse returns a range: https://dlang.org/phobos/std_algorithm_mutation.html#reverse https://docarchives.dlang.io/v2.078.0/phobos/std_algorithm_mutation.html#reverse This doesn't quite tell the whole story. An array used to have a .reverse property that the compiler implemented, which returned the array after reversing it. So in history, this actually worked without std.algorithm. You get a nice history of what happens using "all dmd versions" on run.dlang.io. If you remove the "mutation" part from the import, you get: Up to 2.071.2: Success with output: 𐅃Ā𐅃olleh 2.072.2 to 2.074.1: Success with output: - onlineapp.d(6): Deprecation: use std.algorithm.reverse instead of .reverse property 𐅃Ā𐅃olleh - 2.075.1: Failure with output: - onlineapp.d(6): Error: template std.stdio.writeln cannot deduce function from argument types !()(void), candidates are: /path/to/dmd.linux/dmd2/linux/bin64/../../src/phobos/std/stdio.d(3553): std.stdio.writeln(T...)(T args) - 2.076.1 to 2.077.1: Failure with output: - onlineapp.d(6): Error: template std.stdio.writeln cannot deduce function from argument types !()(void), candidates are: /path/to/dmd.linux/dmd2/linux/bin64/../../src/phobos/std/stdio.d(3571): std.stdio.writeln(T...)(T args) - 2.078.1: Failure with output: - onlineapp.d(6): Error: template std.stdio.writeln cannot deduce function from argument types !()(void), candidates are: /path/to/dmd.linux/dmd2/linux/bin64/../../src/phobos/std/stdio.d(3657): std.stdio.writeln(T...)(T args) - Since 2.079.0: Success with output: 𐅃Ā𐅃olleh -Steve
return type of std.algorithm.mutation.reverse changed for good?
I am testing with DMD 2.078.2 locally. This tiny snippet works on dlang's online editor: https://run.dlang.io/is/nb4IV4 But it does not work on my local dmd. import std.algorithm.mutation; import std.stdio; char[] arr = "hello\U00010143\u0100\U00010143".dup; writeln(arr.reverse); Error: template std.stdio.writeln cannot deduce function from argument types !()(void) The document says reverse returns a range: https://dlang.org/phobos/std_algorithm_mutation.html#reverse
Re: return type of std.algorithm.mutation.reverse changed for good?
On 25/05/2018 12:06 AM, biocyberman wrote: I am testing with DMD 2.078.2 locally. This tiny snippet works on dlang's online editor: https://run.dlang.io/is/nb4IV4 But it does not work on my local dmd. import std.algorithm.mutation; import std.stdio; char[] arr = "hello\U00010143\u0100\U00010143".dup; writeln(arr.reverse); Error: template std.stdio.writeln cannot deduce function from argument types !()(void) The document says reverse returns a range: https://dlang.org/phobos/std_algorithm_mutation.html#reverse https://docarchives.dlang.io/v2.078.0/phobos/std_algorithm_mutation.html#reverse
Re: Deleting a file with extsion *.FIFO in Windows
On Thursday, 24 May 2018 at 06:59:47 UTC, Vino wrote: Hi All, Request your help on how to delete a file which has the extension .fifo (.javast.fifo) in Windows. From, Vino.B What exactly is your issue with it?
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 10:42:26 UTC, Andrea Fontana wrote: On Thursday, 24 May 2018 at 10:23:41 UTC, Andrea Fontana wrote: On Thursday, 24 May 2018 at 09:17:10 UTC, Alex wrote: On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";"); Whoops I didn't get it. Thank you both. Andrea Why didn't that return any error, anyway? Because: mixin("alias tmp = " ~ s ~ ";"); Translates to: alias tmp = i; And i will be the global i.
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 10:23:41 UTC, Andrea Fontana wrote: On Thursday, 24 May 2018 at 09:17:10 UTC, Alex wrote: On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";"); Whoops I didn't get it. Thank you both. Andrea Why didn't that return any error, anyway?
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 09:17:10 UTC, Alex wrote: On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";"); Whoops I didn't get it. Thank you both. Andrea
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";");
Re: Translate C/C++ patern: return a pointer
On Thursday, 24 May 2018 at 08:58:02 UTC, Nicholas Wilson wrote: On Thursday, 24 May 2018 at 08:16:30 UTC, biocyberman wrote: [...] it looks like Read is a D class? in which case it already returns by reference. If you make Read a struct then all you need do is change the function signature from Read reverseComplement() to Read* reverseComplement() about the function body use mQuality.dup.representation.reverse; [...] does not do what you want it to do. Thanks for the hints. `Read` in C++ and D are both classes. And the function is inside the class definition itself.
Re: Translate C/C++ patern: return a pointer
On Thursday, 24 May 2018 at 08:16:30 UTC, biocyberman wrote: Some C and C++ projects I am working on use pointers and references extensively: to pass as function arguments, and to return from a function. For function argument I would use `ref`, but for return types, I can't use `ref` and can't return a pointer. What should be the proper way to handle this? Do I have to change function signature (i.e. return type) For example, the following function: ``` //C++ version, from: https://github.com/bioslaD/fastp/blob/orig/src/read.cpp#L69 Read* Read::reverseComplement(){ Sequence seq = ~mSeq; string qual; qual.assign(mQuality.rbegin(), mQuality.rend()); string strand = (mStrand=="+") ? "-" : "+"; return new Read(mName, seq, strand, qual); } // D version: Read reverseComplement(){ Sequence seq = ~mSeq; dchar[] qual = cast(dchar[])mQuality.dup; reverse(qual); string strand = (mStrand=="+") ? "-" : "+"; Read newRead = new Read(mName, seq, strand, cast(string)qual); // return &newRead does not work: returning `& newRead` escapes a reference to local variable newRead return newRead; } ``` Let's not focus on the function body, I don't know how to handle the return type in cases like this for the D version. it looks like Read is a D class? in which case it already returns by reference. If you make Read a struct then all you need do is change the function signature from Read reverseComplement() to Read* reverseComplement() about the function body use mQuality.dup.representation.reverse; dchar[] qual = cast(dchar[])mQuality.dup; reverse(qual); mQuality = cast(string)qual; does not do what you want it to do.
Re: Efficient idiom for fastest code
On Wednesday, 23 May 2018 at 03:12:52 UTC, IntegratedDimensions wrote: On Wednesday, 23 May 2018 at 03:00:17 UTC, Nicholas Wilson wrote: [...] I knew someone was going to say that and I forgot to say DON'T! Saying to profile when I clearly said these ARE cases where they are slow is just moronic. Please don't use default answers to arguments. This was a general question about cases on how to attack a problem WHEN profiling says I need to optimize. Your SO 101 answer sucks! Sorry! To prove to you that your answer is invalid: I profile my code, it says that it is very slow and shows that it is do to the decision checking... I then I have to come here and write up a post trying to explain how to solve the problem. I then get a post telling me I should profile. I then respond I did profile and that this is my problem. A lot of wasted energy when it is better to know a general attack strategy. Yes, some of us can judge if code is needed to be optimized before profiling. It is not difficult. Giving a generic answer that always does not apply and is obvious to anyone trying to do optimization is not helpful. Everyone today pretty must does not even optimize code anymore... this isn't 1979. It's not ok to keep repeating the same mantra. I guess we should turn this in to a meme? The reason I'm getting on to you is that the "profile before optimization" sounds a bit grade school, specially since I wasn't talking anything about profiling but a general programming pattern speed up code, which is always valid but not always useful(and hence that is when profiling comes in). Very challenging. Wish I could help you out with the tough work. People don't share the same context, especially via online, so it is necessary to clarify the problem so other can understand and help. I've been beaten on stackoverflow many times for not providing sufficient information for my questions. It seems like one can do the reverse here at forum.dlang.org. With that said, I think you know what you are doing, and you can do it. Just relax and give it more time and experimentation.
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 07:59:08 UTC, Simen Kjærås wrote: On Thursday, 24 May 2018 at 07:47:54 UTC, Andrea Fontana wrote: Is this a bug or am I missing something? https://run.dlang.io/is/OGHJYX Andrea This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What?
Translate C/C++ patern: return a pointer
Some C and C++ projects I am working on use pointers and references extensively: to pass as function arguments, and to return from a function. For function argument I would use `ref`, but for return types, I can't use `ref` and can't return a pointer. What should be the proper way to handle this? Do I have to change function signature (i.e. return type) For example, the following function: ``` //C++ version, from: https://github.com/bioslaD/fastp/blob/orig/src/read.cpp#L69 Read* Read::reverseComplement(){ Sequence seq = ~mSeq; string qual; qual.assign(mQuality.rbegin(), mQuality.rend()); string strand = (mStrand=="+") ? "-" : "+"; return new Read(mName, seq, strand, qual); } // D version: Read reverseComplement(){ Sequence seq = ~mSeq; dchar[] qual = cast(dchar[])mQuality.dup; reverse(qual); string strand = (mStrand=="+") ? "-" : "+"; Read newRead = new Read(mName, seq, strand, cast(string)qual); // return &newRead does not work: returning `& newRead` escapes a reference to local variable newRead return newRead; } ``` Let's not focus on the function body, I don't know how to handle the return type in cases like this for the D version.
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 07:47:54 UTC, Andrea Fontana wrote: Is this a bug or am I missing something? https://run.dlang.io/is/OGHJYX Andrea This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen
UDA and static struct fields
Is this a bug or am I missing something? https://run.dlang.io/is/OGHJYX Andrea
Deleting a file with extsion *.FIFO in Windows
Hi All, Request your help on how to delete a file which has the extension .fifo (.javast.fifo) in Windows. From, Vino.B