Re: DMD on ARM/Linux (for controlling EV3 Lego Mindstorm)?
On 22/08/2016 5:22 PM, Sai wrote: Thanks all for your replies. I tried to use GDC first, I couldn't find windows binary targeting windows (for initial testing) which I thought was weird. https://gdcproject.org/downloads So I tried to build it in Cygwin env, using these instructions: http://wiki.dlang.org/GDC/Installation/Generic (I used gcc-5.2 sources for this). Unfortunately, it failed with the following error. Any ideas? I am tempting towards go, looks like their windows binary supports compiling to both windows and arm. Unfortunately I don't want to use go as it lacks templates (or generics) and operator overloading, as I tend to use lot of vector/matrix math in my programs. gcc/d/dfrontend -Id ../../gcc-5.2.0/gcc/d/dfrontend/filename.c ../../gcc-5.2.0/gcc/d/dfrontend/filename.c: In static member function ‘static bool FileName::ensurePathExists(const char*)’: ../../gcc-5.2.0/gcc/d/dfrontend/filename.c:602:43: error: ‘sep’ was not declared in this scope if (path[strlen(path) - 1] != sep) ^ ../../gcc-5.2.0/gcc/d/dfrontend/filename.c:611:21: error: ‘r’ was not declared in this scope if (r) ^ ../../gcc-5.2.0/gcc/d/dfrontend/filename.c:616:25: error: ‘errno’ was not declared in this scope if (errno != EEXIST) ^ ../../gcc-5.2.0/gcc/d/dfrontend/filename.c:616:34: error: ‘EEXIST’ was not declared in this scope if (errno != EEXIST) ^ make[2]: *** [../../gcc-5.2.0/gcc/d/Make-lang.in:115: d/filename.o] Error 1 make[2]: *** Waiting for unfinished jobs rm gcc.pod gdc.pod make[2]: Leaving directory '/home/sai/gdc/objdir/gcc' make[1]: *** [Makefile:4127: all-gcc] Error 2 make[1]: Leaving directory '/home/sai/gdc/objdir' make: *** [Makefile:867: all] Error 2 I've seen that error before, specifically not finding errno. If I remember right its not using the right c++ language version. That is what you should try and Google. I would do it myself but I can't right this minute.
Re: DMD on ARM/Linux (for controlling EV3 Lego Mindstorm)?
Thanks all for your replies. I tried to use GDC first, I couldn't find windows binary targeting windows (for initial testing) which I thought was weird. https://gdcproject.org/downloads So I tried to build it in Cygwin env, using these instructions: http://wiki.dlang.org/GDC/Installation/Generic (I used gcc-5.2 sources for this). Unfortunately, it failed with the following error. Any ideas? I am tempting towards go, looks like their windows binary supports compiling to both windows and arm. Unfortunately I don't want to use go as it lacks templates (or generics) and operator overloading, as I tend to use lot of vector/matrix math in my programs. gcc/d/dfrontend -Id ../../gcc-5.2.0/gcc/d/dfrontend/filename.c ../../gcc-5.2.0/gcc/d/dfrontend/filename.c: In static member function ‘static bool FileName::ensurePathExists(const char*)’: ../../gcc-5.2.0/gcc/d/dfrontend/filename.c:602:43: error: ‘sep’ was not declared in this scope if (path[strlen(path) - 1] != sep) ^ ../../gcc-5.2.0/gcc/d/dfrontend/filename.c:611:21: error: ‘r’ was not declared in this scope if (r) ^ ../../gcc-5.2.0/gcc/d/dfrontend/filename.c:616:25: error: ‘errno’ was not declared in this scope if (errno != EEXIST) ^ ../../gcc-5.2.0/gcc/d/dfrontend/filename.c:616:34: error: ‘EEXIST’ was not declared in this scope if (errno != EEXIST) ^ make[2]: *** [../../gcc-5.2.0/gcc/d/Make-lang.in:115: d/filename.o] Error 1 make[2]: *** Waiting for unfinished jobs rm gcc.pod gdc.pod make[2]: Leaving directory '/home/sai/gdc/objdir/gcc' make[1]: *** [Makefile:4127: all-gcc] Error 2 make[1]: Leaving directory '/home/sai/gdc/objdir' make: *** [Makefile:867: all] Error 2
Re: Float values are wrong in union
On Monday, 22 August 2016 at 04:52:40 UTC, Cauterite wrote: On Monday, 22 August 2016 at 04:37:50 UTC, stunaep wrote: I made a union to convert between int bits and floats, but the values are coming out wrong sometimes. I can already tell what this is going to be... The problem is almost certainly nothing to do with your union, it's this line: float t2 = t.f; This will load 0x7fb0 into ST(0), which instantly converts it to 7FF0 because it's a signalling NaN, then store ST(0) in your float `t2`. Signalling NaNs are an ongoing problem in D's codegen. See Don's remarks at this page: https://issues.dlang.org/show_bug.cgi?id=16105#c2 The reason it works in other languages is because they don't place floats in the floating point registers for non-arithmetic operations. I've been trying to patch DMD's backend to behave this way too, but it's much harder than I expected (difficult codebase to understand/navigate). That's a 32 bit codegen issue then because DMD64 's disasm shows that SSE regs are used: void foo() { union test { int i; float f; } test t = { i : 0x7fb0}; float t2 = t.f; test t3 = { f : t2 }; } === yields to === 004586D0h push rbp 004586D1h mov rbp, rsp 004586D4h sub rsp, 10h 004586D8h mov dword ptr [rbp-10h], 7FB0h 004586DFh movss xmm0, dword ptr [rbp-10h] 004586E4h movss dword ptr [rbp-0Ch], xmm0 004586E9h movss xmm1, dword ptr [rbp-0Ch] 004586EEh movss dword ptr [rbp-08h], xmm1 004586F3h leave 004586F4h ret ===
Re: Float values are wrong in union
On Monday, 22 August 2016 at 04:37:50 UTC, stunaep wrote: I made a union to convert between int bits and floats, but the values are coming out wrong sometimes. I can already tell what this is going to be... The problem is almost certainly nothing to do with your union, it's this line: float t2 = t.f; This will load 0x7fb0 into ST(0), which instantly converts it to 7FF0 because it's a signalling NaN, then store ST(0) in your float `t2`. Signalling NaNs are an ongoing problem in D's codegen. See Don's remarks at this page: https://issues.dlang.org/show_bug.cgi?id=16105#c2 The reason it works in other languages is because they don't place floats in the floating point registers for non-arithmetic operations. I've been trying to patch DMD's backend to behave this way too, but it's much harder than I expected (difficult codebase to understand/navigate).
Re: Float values are wrong in union
On Monday, 22 August 2016 at 04:37:50 UTC, stunaep wrote: I made a union to convert between int bits and floats, but the values are coming out wrong sometimes. This is working without issue in other languages so I'm really stumped. Here's an example: union test { int i; float f; } test t = { i : 0x7fb0}; float t2 = t.f;//int bits 0x7fb0 as float test t3 = { f : t2 }; writefln("%x", t3.i);//prints 7ff0 NOT 0x7fb0 Ok on linux, 0x7fb0 is written, I tested under linux x86_64 with latest dmd beta, ldc and also gdc. Which compiler and version do you use ? Which OS and archi ?
Float values are wrong in union
I made a union to convert between int bits and floats, but the values are coming out wrong sometimes. This is working without issue in other languages so I'm really stumped. Here's an example: union test { int i; float f; } test t = { i : 0x7fb0}; float t2 = t.f;//int bits 0x7fb0 as float test t3 = { f : t2 }; writefln("%x", t3.i);//prints 7ff0 NOT 0x7fb0
Re: Is there a d analog of strncmp?
On Monday, 22 August 2016 at 01:45:02 UTC, Jonathan M Davis wrote: On Monday, August 22, 2016 00:14:31 Adam D. Ruppe via Digitalmars-d-learn wrote: int strncmp(string a, string b, int n) { if(a.length > n) a = a[0 .. n]; if(b.length > n) b = b[0 .. n]; import std.algorithm.comparison : cmp; return cmp(a, b); } Aside from the imports, it can be turned into a one-liner if you use take: return cmp(take(a, n), take(b, n)); - Jonathan M Davis Thanks Adam and Jonathan for your solutions. For reference, one of the imports Jonathan is referring to is import std.range; I did not know about take. Well, i also did not know about cmp. So my code is probably not very idiomatic. But i do appreciate all of you d-learn people!
Re: Variant and immutable struct
On Sunday, 10 January 2016 at 17:50:44 UTC, Vlad Leberstein wrote: As I'm not very good at D, I would like to get some feedback about this solutions' viability. AFAIU memcpy-ing struct here is safe because all target arguments ever passed to tryPutting are internal to implementation(and SHOULD be void-initialized but it's currently not working AFAIK). Maybe postblit should also be called for new instance, but I'm not sure about current state of qualified postblit. Any help would be greatly appreciated! I am hitting the same problem. Trying to send an immutable hashmap of variants with std.concurrency.
Re: Is there a d analog of strncmp?
On Monday, August 22, 2016 00:14:31 Adam D. Ruppe via Digitalmars-d-learn wrote: > int strncmp(string a, string b, int n) { > if(a.length > n) > a = a[0 .. n]; > if(b.length > n) > b = b[0 .. n]; > import std.algorithm.comparison : cmp; > return cmp(a, b); > } Aside from the imports, it can be turned into a one-liner if you use take: return cmp(take(a, n), take(b, n)); - Jonathan M Davis
Re: Rebind template(bug?)
On Monday, 22 August 2016 at 00:22:48 UTC, ag0aep6g wrote: On 08/22/2016 12:06 AM, Engine Machine wrote: T!()'s "data" is specified in the class just like all the other derivations. I don't want to have to specify an external base class as in your InstaniateOrBase. Why? Because!!! (There should be no need to, and if one goes this route of creating classes, it should be all or nothing, else there is no real benefit) You make it sound like I came up with the external base class, but I just took that from your code. No, what I meant was I don't want a base. I only added it in my code so it would compile/do what I want. [...] It seems that when one uses `class T(A...) : X`, one can't, for some X, not have inheritance. The compiler expects X to be something inheritable from no matter what. I didn't know it, but your code shows that X can also be an empty compile time list (Seq). I have no idea if this is in the spec, or if it just happens to work with dmd. If it's valid D, you just need a template that goes from T and A to T!(A[0 .. $ - 1]), or if A is already empty, to the empty Seq. Like so: template InstantiateOrEmptySeq(alias tmpl, args...) { alias Seq(T...)=T; static if (args.length > 0) alias InstantiateOrEmptySeq = tmpl!(args[0 .. $ - 1]); else alias InstantiateOrEmptySeq = Seq!(); } class T(A...) : InstantiateOrEmptySeq!(T, A) { ... } Yes! I though I tried that from Timon's original solution. The following code works and does what I want! template InstantiateOrEmptySeq(alias tmpl, args...) { alias Seq(T...)=T; static if (args.length > 0) alias InstantiateOrEmptySeq = tmpl!(args[0 .. $-1]); else alias InstantiateOrEmptySeq = Seq!(); } class T(A...) : InstantiateOrEmptySeq!(T, A) { static if (A.length == 0) { // Base class int x; } else static if (A[$-1] == "Animal") { int y; } else static if (A[$-1] == "Dog") { int z; } else static if (A[$-1] == "Pug") { int s; } else static assert(A[$-1]~" not a defined class of "~this.stringof); } The only down side is that the static if's are flat. They don't show the relationship between, say, Dog an Animal, that a nested set of static if's would show, but I think this is not possible due to the recursion and shadowing(I imagine one could test if the variables exist but that is messy). Anyways, Thanks for the help. I think this is just Timons answer anyways. What the original confusion was, was the shadowing, which I thought would not happen(or at least expected an error), Lodovico solved that.
Re: Rebind template(bug?)
On 08/22/2016 12:06 AM, Engine Machine wrote: T!()'s "data" is specified in the class just like all the other derivations. I don't want to have to specify an external base class as in your InstaniateOrBase. Why? Because!!! (There should be no need to, and if one goes this route of creating classes, it should be all or nothing, else there is no real benefit) You make it sound like I came up with the external base class, but I just took that from your code. [...] It seems that when one uses `class T(A...) : X`, one can't, for some X, not have inheritance. The compiler expects X to be something inheritable from no matter what. I didn't know it, but your code shows that X can also be an empty compile time list (Seq). I have no idea if this is in the spec, or if it just happens to work with dmd. If it's valid D, you just need a template that goes from T and A to T!(A[0 .. $ - 1]), or if A is already empty, to the empty Seq. Like so: template InstantiateOrEmptySeq(alias tmpl, args...) { alias Seq(T...)=T; static if (args.length > 0) alias InstantiateOrEmptySeq = tmpl!(args[0 .. $ - 1]); else alias InstantiateOrEmptySeq = Seq!(); } class T(A...) : InstantiateOrEmptySeq!(T, A) { ... }
Re: Is there a d analog of strncmp?
int strncmp(string a, string b, int n) { if(a.length > n) a = a[0 .. n]; if(b.length > n) b = b[0 .. n]; import std.algorithm.comparison : cmp; return cmp(a, b); }
Re: Creating an array of user-defined structs
On Sunday, 21 August 2016 at 23:57:27 UTC, brian wrote: I understand it's a map, but does my syntax not define an Associative Array?? yeah, it is. If that's what you want, good! So I wanted something dynamic. OK, then you should use pointers so you can have several references to the same object in different maps (so you can have one for ID, one for name, etc.). Just make it testStruct*[int] testStructArray; and then try compiling the rest basically as it is, newing the struct, it should work.
Is there a d analog of strncmp?
In c, there's this very nice function strncmp(s1,s2,count) which compares two c strings, using at most count characters. count can be less than, more than, or equal to either or both of the lengths of the two strings. It can be used to see if two c-strings have the same prefix of some length. Now, strncmp indeed seems to be packaged up in core.stdc.string, but i would like to use some something like it on 2 d strings (which, as i understand it, need not be zero-terminated). I suppose it would be possible to do some conversion with toStringz() or something and then invoke the strncmp(), but that seems very wordy and also it's not clear that it would handle all pairs of d strings (e.g., what if there were some 0's in the first count characters?). So i would like to call a d function which works on d strings, but don't want to write my own if one already exists. (At the very least, i'd have to get a much sharper understanding of d strings, whether internal 0's can occur, etc. And i would not want to do egregious string allocation.) TIA for any info!
Re: Creating an array of user-defined structs
Thanks Adam. Couple of follow up questions, if you don't mind: On Sunday, 21 August 2016 at 23:37:38 UTC, Adam D. Ruppe wrote: testStruct[int] testStructArray; That's not actually an array per se, that is a key/value map where the keys are ints. I understand it's a map, but does my syntax not define an Associative Array?? https://dlang.org/spec/hash-map.html That's kinda what I wanted because I want to be able to look up the Structs by the value of int. Either do a traditional array and copy struct values onto it or do an array of pointers and new them. Which option is bsed depends on the details of what you're doing. This was a simple example of what I wanted to illustrate the problem. What I probably want for my future program state is some sort of hash map, as I'll be using this "array" as a lookup table. So conceptually something like: userid | username | structs 0001 | brian| structAboutBrian 0002 | john | structAboutJohn I probably want to be able to look up info using either userid, or username, but I can settle for one of them I'm creating the entries during execution of the program, so I have no idea how big the structure is going to be. So I wanted something dynamic. I'm a bit of a novice in terms of theoretical comp sci, so I'm not sure what data structure would be best suited to something like that, or how to implement. Happy to take advice. :)
Re: Creating an array of user-defined structs
On Sunday, 21 August 2016 at 23:28:14 UTC, brian wrote: /* creates(?) an empty array of structs */ testStruct[int] testStructArray; That's not actually an array per se, that is a key/value map where the keys are ints. So you can set values to it at any position in it but not append or do other traditional array operations. An ordinary array is defined with testStruct[] testStructArray; though what you have isn't necessarily wrong. auto newStruct = new testStruct; This is the cause of the pointer mismatch error - new struct returns a pointer to it. If you just want an ordinary struct you define it: testStruct newStruct; like that. newStruct.aa = a.dup; newStruct.bb = b.dup; No need for the .dup there because strings aren't going to be changing under you anyway. 1) I'm assuming by the error that line 23 defines a pointer rather than a ... not-pointer thing. I'm not sure why it is doing that, and would like some explanation please. :) It is just how new works in D, it returns a reference. For structs, that means a pointer to it. 2) Is this the best way to do what I am trying to do, which is dynamically grow an array of user defined structs? Either do a traditional array and copy struct values onto it or do an array of pointers and new them. Which option is bsed depends on the details of what you're doing.
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 21:11:37 UTC, ag0aep6g wrote: On 08/21/2016 09:29 PM, Engine Machine wrote: I know you like to play the right or wrong game, but did you ever learn that a single example does not prove the truth of something? But you can show in a single example that something doesn't work. You tried to do that, and you did it with a simple example, which is always appreciated. But apparently, you were wrong. Happens to the best. And when the compiler prints "tmpl!a" that's indeed a little misleading. You being wrong there doesn't mean that the Rebind template as I posted it works correctly, of course. But Jack didn't claim that. He just said that your example for how it doesn't work is wrong. And as far as I see, Rebind does work as expected. But I wouldn't be surprised if there is some edge case where things fall apart. Also, if you're looking for help or civil discussion, I suggest you try a less antagonistic approach. Things like "I know you like to [play games]" and "did you ever learn [whatever]" do not set the tone for that. How about something more complex? import std.stdio; import std.meta, std.traits; class base { } Style nitpick: Class names in PascalCase, please. template Rebind(alias instance, newArgs...) { import std.traits: TemplateOf; alias tmpl = TemplateOf!instance; static if (newArgs.length > 0) alias Rebind = tmpl!newArgs; else alias Rebind = base; } template EraseLast(A...) { static if (A.length > 0) alias EraseLast = Erase!(A[$-1], A); This line can be simplified: alias EraseLast = A[0 .. $ - 1]; else alias EraseLast = base; This is quite surprising for a template that's called "EraseLast". I renamed it to "EraseLastOrBase" for myself when looking at this. } class T(A...) : Rebind!(T!A, EraseLast!A) The core idea of Rebind isn't needed here, is it? You've got T, so you can just pass it directly. No need to extract it from T!A. So, instead of using some form of Rebind, you can use a simpler template: /* Instantiates tmpl with args, or if no args given, returns base. */ template InstantiateOrBase(alias tmpl, args ...) { static if (args.length == 0) alias InstantiateOrBase = base; else alias InstantiateOrBase = tmpl!args; } class T(A...) : InstantiateOrBase!(T, EraseLast!A) { int x; Note that this means that every instantiation of T brings its own x. That is, T!foo declares an x, and T!(foo, bar) which inherits from T!foo adds another x. The same happens with y, z, and s, of course. static if (A.length > 0 && A[0] == "Animal") { int y; static if (A.length > 1 && A[1] == "Dog") { int z; static if (A.length > 2 && A[2] == "Pug") int s; } } } pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal", "Dog"))); pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal"))); pragma(msg, is(T!("Animal", "Dog", "Pug") : base)); pragma(msg, is(T!("Animal", "Dog") : T!("Animal"))); pragma(msg, is(T!("Animal", "Dog") : base)); pragma(msg, is(T!("Animal") : base)); Asserts are great to show that something holds. When someone like me makes changes to your code in order to understand it, the complier throws a nice loud error in their face when they mess up. So I changed these to static asserts for myself. // all true void main() { auto t = new T!("Animal", "Dog", "Pug")(); T!("Animal", "Dog") q = t; //T!("Animal", "Dog", "Pug") q = t; works but then q is not the super of t t.x = 3; t.y = 4; t.z = 6; t.s = 123; q.y = 1; writeln(t, ", ", typeof(t).stringof); writeln(q, ", ", typeof(q).stringof); writeln("---"); writeln(t.x); writeln(t.y); writeln(t.z); writeln(t.s); writeln("---"); writeln(q.x); writeln(q.y); writeln(q.z); writeln("---"); writeln(t.y); writeln("---"); writeln(); writeln(); } Since the pragma's are true, it is obvious that the inheritance should work chain works. Yet q is not a reference to t as it should be, why is this? It would help a lot if you would point out what parts of the output are surprising to you. If you let the reader figure it out themselves, chances are 1) people are not going to bother, and 2) if they do bother, they might miss your point. Labeling the output also helps. By that I mean, if you write `writeln("t.x: ", t.x);`, the output can be read much more easily. I also think that you could have made your point with less output, which would again make it easier to follow. That is, just looking t.x/q.x would have been enough, no? I guess you expect q.x and friends to be the same as t.x and friends. And since you put it there, you may also expect to be the same as About the members being different: That's because every instantiation brings its own x/y/z, as mentioned above. Lodovico has
Re: Rebind template(bug?)
On 08/21/2016 09:29 PM, Engine Machine wrote: I know you like to play the right or wrong game, but did you ever learn that a single example does not prove the truth of something? But you can show in a single example that something doesn't work. You tried to do that, and you did it with a simple example, which is always appreciated. But apparently, you were wrong. Happens to the best. And when the compiler prints "tmpl!a" that's indeed a little misleading. You being wrong there doesn't mean that the Rebind template as I posted it works correctly, of course. But Jack didn't claim that. He just said that your example for how it doesn't work is wrong. And as far as I see, Rebind does work as expected. But I wouldn't be surprised if there is some edge case where things fall apart. Also, if you're looking for help or civil discussion, I suggest you try a less antagonistic approach. Things like "I know you like to [play games]" and "did you ever learn [whatever]" do not set the tone for that. How about something more complex? import std.stdio; import std.meta, std.traits; class base { } Style nitpick: Class names in PascalCase, please. template Rebind(alias instance, newArgs...) { import std.traits: TemplateOf; alias tmpl = TemplateOf!instance; static if (newArgs.length > 0) alias Rebind = tmpl!newArgs; else alias Rebind = base; } template EraseLast(A...) { static if (A.length > 0) alias EraseLast = Erase!(A[$-1], A); This line can be simplified: alias EraseLast = A[0 .. $ - 1]; else alias EraseLast = base; This is quite surprising for a template that's called "EraseLast". I renamed it to "EraseLastOrBase" for myself when looking at this. } class T(A...) : Rebind!(T!A, EraseLast!A) The core idea of Rebind isn't needed here, is it? You've got T, so you can just pass it directly. No need to extract it from T!A. So, instead of using some form of Rebind, you can use a simpler template: /* Instantiates tmpl with args, or if no args given, returns base. */ template InstantiateOrBase(alias tmpl, args ...) { static if (args.length == 0) alias InstantiateOrBase = base; else alias InstantiateOrBase = tmpl!args; } class T(A...) : InstantiateOrBase!(T, EraseLast!A) { int x; Note that this means that every instantiation of T brings its own x. That is, T!foo declares an x, and T!(foo, bar) which inherits from T!foo adds another x. The same happens with y, z, and s, of course. static if (A.length > 0 && A[0] == "Animal") { int y; static if (A.length > 1 && A[1] == "Dog") { int z; static if (A.length > 2 && A[2] == "Pug") int s; } } } pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal", "Dog"))); pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal"))); pragma(msg, is(T!("Animal", "Dog", "Pug") : base)); pragma(msg, is(T!("Animal", "Dog") : T!("Animal"))); pragma(msg, is(T!("Animal", "Dog") : base)); pragma(msg, is(T!("Animal") : base)); Asserts are great to show that something holds. When someone like me makes changes to your code in order to understand it, the complier throws a nice loud error in their face when they mess up. So I changed these to static asserts for myself. // all true void main() { auto t = new T!("Animal", "Dog", "Pug")(); T!("Animal", "Dog") q = t; //T!("Animal", "Dog", "Pug") q = t; works but then q is not the super of t t.x = 3; t.y = 4; t.z = 6; t.s = 123; q.y = 1; writeln(t, ", ", typeof(t).stringof); writeln(q, ", ", typeof(q).stringof); writeln("---"); writeln(t.x); writeln(t.y); writeln(t.z); writeln(t.s); writeln("---"); writeln(q.x); writeln(q.y); writeln(q.z); writeln("---"); writeln(t.y); writeln("---"); writeln(); writeln(); } Since the pragma's are true, it is obvious that the inheritance should work chain works. Yet q is not a reference to t as it should be, why is this? It would help a lot if you would point out what parts of the output are surprising to you. If you let the reader figure it out themselves, chances are 1) people are not going to bother, and 2) if they do bother, they might miss your point. Labeling the output also helps. By that I mean, if you write `writeln("t.x: ", t.x);`, the output can be read much more easily. I also think that you could have made your point with less output, which would again make it easier to follow. That is, just looking t.x/q.x would have been enough, no? I guess you expect q.x and friends to be the same as t.x and friends. And since you put it there, you may also expect to be the same as About the members being different: That's because every instantiation brings its own x/y/z, as mentioned above. Lodovico has shown what happens here in his Child/Parent example. About and : Those are the
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 20:36:54 UTC, Engine Machine wrote: On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta wrote: [...] You're right. I didn't realize that variables could be shadowed in classes. Seems dangerous. D doesn't allow shadowing in a normal context and gives an error so I don't know why it wouldn't do that in classes. (since it wasn't giving an error I thought it wasn't shadowing) You are right. It is very bad. But as far as I know Java and C++ allow this too. I will open an enhancement request (if there's none about this), to gather some feedback on the matter.
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta wrote: On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote: [...] The problem of this code has nothing to do with aliases. They work correctly. The problem is variable shadowing. In the following code, Child has two x variables, one of which is only accessible from a Parent reference, the other only from a Child reference. class Parent { int x; } class Child: Parent { int x; // this shadows Parent.x int y; } void main() { Child child = new Child(); Parent parent = child; child.x = child.y = 3; parent.x = 2; assert(child.x == 3); assert((cast(Child)parent).x == 3); assert((cast(Parent)child).x == 2); assert(parent is child); // same object (remember that a class is already a pointer); assert( != ); // but there are two different pointers on the stack (pointing to the same object) } You're right. I didn't realize that variables could be shadowed in classes. Seems dangerous. D doesn't allow shadowing in a normal context and gives an error so I don't know why it wouldn't do that in classes. (since it wasn't giving an error I thought it wasn't shadowing)
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote: I know you like to play the right or wrong game, but did you ever learn that a single example does not prove the truth of something? How about something more complex? Your demagogy will not help you learn the basics of the D language. And you're wrong again, young arrogant padawan.
Re: Sequence separation
On Wednesday, 17 August 2016 at 19:38:22 UTC, Engine Machine wrote: Well, the is does work and that probably is the best solution. I don't mind the extra type at this point. Of course, a library solution for this type of stuff would be nice. I'd rather not have to even use a type but rather use arrays: [a,b,[c,d]]. Maybe you can use Tuple from std.typecons, instead of custom structs, that group the arguments. Ex: alias seqWithSubSeq = AliasSeq!(a, b, Tuple!(c, d)) http://dlang.org/phobos/std_typecons.html#.Tuple
Re: Rebind template
On Saturday, 20 August 2016 at 22:18:57 UTC, Engine Machine wrote: On Saturday, 20 August 2016 at 22:11:40 UTC, Engine Machine wrote: Is there a way to rebind the arguments of a template? template foo(X) { // X is like A!(a,b,c) Y = Rebind!(X,d,e,f); // Y is like A!(d,e,f); } foo(A!(a,b,c)); ? I'd also be happy if I could just remove the last element from A. template EraseLast(X) { // returns A!(a,b) when X = A!(a,b,c) } Check for ApplyLeft and ApplyRight in std.meta, maybe it can help you. http://dlang.org/phobos/std_meta.html#.ApplyLeft http://dlang.org/phobos/std_meta.html#.ApplyRight
How to avoid ctRegex (solved)
At seconds PER (character range) pattern, ctRegex slows down compilation like crazy, but it's not obvious how to avoid using it, since Regex(Char) is kind of weird for a type. So, here's what I do. I think this is right. in the module scope, you start with: auto pattern = ctRegex!"foobar"; and you substitute with: typeof(regex("")) pattern; static this() { pattern = regex("foobar"); } That way you don't have to worry about whether to use a Regex!char, or a Regex!dchar, or a Regex!ubyte. It gives you the same functionality, at the cost a few microseconds slowdown on running your program. And once you're done debugging, you can always switch back, so... string defineRegex(string name, string pattern)() { import std.string: replace; return q{ debug { pragma(msg, "fast $name"); import std.regex: regex; typeof(regex("")) $name; static this() { $name = regex(`$pattern`); } } else { pragma(msg, "slooow $name"); import std.regex: ctRegex; auto $name = ctRegex!`$pattern`; } }.replace("$pattern",pattern) .replace("$name",name); } mixin(defineRegex!("naword",r"[\W]+")); mixin(defineRegex!("alnum",r"[a-zA-Z]+")); mixin(defineRegex!("pattern","foo([a-z]*?)bar")); mixin(defineRegex!("pattern2","foobar([^0-9z]+)")); void main() { } /* $ time rdmd -release /tmp/derp.d slooow naword slooow alnum slooow pattern slooow pattern2 slooow naword slooow alnum slooow pattern slooow pattern2 rdmd -release /tmp/derp.d 17.57s user 1.57s system 82% cpu 23.210 total $ time rdmd -debug /tmp/derp.d fast naword fast alnum fast pattern fast pattern2 fast naword fast alnum fast pattern fast pattern2 rdmd -debug /tmp/derp.d 2.92s user 0.37s system 71% cpu 4.623 total */ ...sure would be nice if you could cache precompiled regular expressions as files.
Re: Mem Mgmt: With & Without the GC
Thanks to both of you. I think that answers everything, except if new'd objects can be freed when GC is disabled. I guess I could always enable and call collect().
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 19:42:08 UTC, Lodovico Giaretta wrote: On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote: [...] The problem of this code has nothing to do with aliases. They work correctly. The problem is variable shadowing. In the following code, Child has two x variables, one of which is only accessible from a Parent reference, the other only from a Child reference. class Parent { int x; } class Child: Parent { int x; // this shadows Parent.x int y; } void main() { Child child = new Child(); Parent parent = child; child.x = child.y = 3; parent.x = 2; assert(child.x == 3); assert((cast(Child)parent).x == 3); assert((cast(Parent)child).x == 2); assert(parent is child); // same object (remember that a class is already a pointer); assert( != ); // but there are two different pointers on the stack (pointing to the same object) } A patch to your code that makes it work, with the parts not displayed unchanged: class base { int x; } class T(A...) : Rebind!(T!A, EraseLast!A) { static if(A[$-1] == "Animal") int y; else static if (A[$-1] == "Dog") int z; else static if (A[$-1] == "Pug") int s; }
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 19:29:26 UTC, Engine Machine wrote: [...] The problem of this code has nothing to do with aliases. They work correctly. The problem is variable shadowing. In the following code, Child has two x variables, one of which is only accessible from a Parent reference, the other only from a Child reference. class Parent { int x; } class Child: Parent { int x; // this shadows Parent.x int y; } void main() { Child child = new Child(); Parent parent = child; child.x = child.y = 3; parent.x = 2; assert(child.x == 3); assert((cast(Child)parent).x == 3); assert((cast(Parent)child).x == 2); assert(parent is child); // same object (remember that a class is already a pointer); assert( != ); // but there are two different pointers on the stack (pointing to the same object) }
Re: Mem Mgmt: With & Without the GC
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote: Hey all, My knowledge of GCs is limited, but my faith in them (for most applications) has greatly increased with advances (like with Golang's recent updates). I am now trying to get a better sense for the direction D is going regarding memory management, both in relation to the GC and without it. Excuse my ignorance, but can someone clarify the following for me? 1) If using the GC, but for whatever reason, I need to free something _right now_, is core.GC.free() the proper way to do this? If you need to destroy a class object right now, the proper way is to call .destroy on it (or use something that uses it like Scoped!T, Unique!T, Refcounted!T...). If you need to destroy a struct object right now, the proper way is to end the scope. If you need to free memory right now, better not allocate it from the GC, but instead with malloc/free. The GC does not guarantee to collect freed memory when you want. 2) Does calling object.destroy() mean that the object is marked for future collection? If not, how can I ensure it is properly marked. Calling .destoy on an object calls its destructor but does not mark it for collection. Objects are collected when they are not reachable anymore. At this point, the destructor is called if it wasn't already (and then the object is overwritten with .init). Actually you shouldn't have to worry when an object memory is collected. 3) How can I mark a non-object for future collection? For example, a dynamic array: int[] a = new int[10];. Do I just set any references to null? Yes, it is marked for future collection when it's not reachable anymore. Then again, the GC might not reclaim memory right now because it's imprecise and you could have "false pointers". 4) What if I want to immediately deallocate a dynamically allocated non-object (such as the dynamic array) - Can I use core.GC.free? I don't know if this will deallocate with 100% certainty. 5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to? Keep a reference somewhere reachable (by default: stack, heap, globals: everything is reachable and scanned). 6) If the GC is off, how is allocation/deallocation handled? If you have called GC.disable, no GC collect is performed on any allocation. This is only suitable if you don't have a long-running software that would risk running out of memory. This is known to speed-up short processes. Can I still use new for example You can still use new. (and how do I dealloc)? I don't know then if you can deallocate.
Re: Rebind template(bug?)
On Sunday, 21 August 2016 at 06:28:25 UTC, Jack Applegame wrote: On Sunday, 21 August 2016 at 00:06:07 UTC, Engine Machine wrote: On Saturday, 20 August 2016 at 22:21:00 UTC, ag0aep6g wrote: On 08/21/2016 12:11 AM, Engine Machine wrote: Is there a way to rebind the arguments of a template? template foo(X) { // X is like A!(a,b,c) Y = Rebind!(X,d,e,f); // Y is like A!(d,e,f); } foo(A!(a,b,c)); ? template Rebind(alias instance, newArgs...) { import std.traits: TemplateOf; alias tmpl = TemplateOf!instance; alias Rebind = tmpl!newArgs; } This doesn't work because the rebound type is of type tmpl and not the original e.g., Rebind!(T!b, a) is tmpl!a not T!a. You are wrong. tmpl is just alias of template T. So tmpl!a and T!a are the same type. alias X = T!(int, short, char); alias Y = Rebind!(X, short, char, int); static assert(is(Y == T!(short, char, int))); // passes I know you like to play the right or wrong game, but did you ever learn that a single example does not prove the truth of something? How about something more complex? import std.stdio; import std.meta, std.traits; class base { } template Rebind(alias instance, newArgs...) { import std.traits: TemplateOf; alias tmpl = TemplateOf!instance; static if (newArgs.length > 0) alias Rebind = tmpl!newArgs; else alias Rebind = base; } template EraseLast(A...) { static if (A.length > 0) alias EraseLast = Erase!(A[$-1], A); else alias EraseLast = base; } class T(A...) : Rebind!(T!A, EraseLast!A) { int x; static if (A.length > 0 && A[0] == "Animal") { int y; static if (A.length > 1 && A[1] == "Dog") { int z; static if (A.length > 2 && A[2] == "Pug") int s; } } } pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal", "Dog"))); pragma(msg, is(T!("Animal", "Dog", "Pug") : T!("Animal"))); pragma(msg, is(T!("Animal", "Dog", "Pug") : base)); pragma(msg, is(T!("Animal", "Dog") : T!("Animal"))); pragma(msg, is(T!("Animal", "Dog") : base)); pragma(msg, is(T!("Animal") : base)); // all true void main() { auto t = new T!("Animal", "Dog", "Pug")(); T!("Animal", "Dog") q = t; //T!("Animal", "Dog", "Pug") q = t; works but then q is not the super of t t.x = 3; t.y = 4; t.z = 6; t.s = 123; q.y = 1; writeln(t, ", ", typeof(t).stringof); writeln(q, ", ", typeof(q).stringof); writeln("---"); writeln(t.x); writeln(t.y); writeln(t.z); writeln(t.s); writeln("---"); writeln(q.x); writeln(q.y); writeln(q.z); writeln("---"); writeln(t.y); writeln("---"); writeln(); writeln(); } Since the pragma's are true, it is obvious that the inheritance should work chain works. Yet q is not a reference to t as it should be, why is this? If aliases were truly aliases as you think(your generic response) then it should work because rebind and erase only use aliases.
Re: Mem Mgmt: With & Without the GC
On Sunday, 21 August 2016 at 18:31:26 UTC, Zane wrote: I see - That makes sense, but is there no way to "pause/stop" the GC, but still be able to use the 'new' syntax? Oh you can use `new` when the GC is disabled, no problem. All the GC's functionality is still available. But be careful about what I said with `new` not returning the base of the allocation. It might not be safe to explicitly `free()` memory allocated by `new` if there could be multiple objects in the same memory block. I honestly don't know the facts about this. You can always `GC.free()` memory you've allocated yourself with `GC.malloc()`, so malloc+emplace is an option. You could define a template to give more convenient syntax. Also I think you can overload the `new` operator. I've never tried it. Regarding the marking, I guess my question is: what must be done to ensure something allocated with 'new' will be a candidate for auto-collection later (when GC is enabled)? I don't think it's possible with a conservative garbage collector, because anything that looks like a pointer to your object can prevent it from being collected. However, if there are no actual live pointers to it, the chances that it will be collected are very high, especially on 64-bit systems. So for now, your best bet is to make sure your object is not accessible (set all live pointers to it to null). It will only stay in memory if you're very unlucky. Once we have a precise garbage collector (should be soon) you can be sure an object will get collected if it is not accessible from any live pointers. -- By the way, when I say "live pointer", I mean a pointer which is accessible (through any number of indirections) from the memory roots. e.g. If you have a linked list on the heap, with each node pointing to the next, but no other pointers to any of the nodes (e.g. from the stack) those pointers are not live. The list as a whole is not accessible.
Re: Mem Mgmt: With & Without the GC
On Sunday, 21 August 2016 at 16:38:09 UTC, Cauterite wrote: On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote: 5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to? I can answer this at least, If you don't want the GC to ever collect the object itself, here's the best way: Allocate the object with a non-GC allocator (such as std.c.malloc ), then use `emplace` to construct the object in that memory ( http://dlang.org/phobos/std_conv.html#.emplace ). I see - That makes sense, but is there no way to "pause/stop" the GC, but still be able to use the 'new' syntax? I like how clear the syntax is, I just don't _always_ want the GC. I'm thinking of something like: core.memory.GC.disable(); Obj o = new Obj(); /* ...use o... */ core.memory.GC.free(o); // or whatever if possible, is there a drawback to this (other than no automatic GC) compared to say, malloc? Regarding the marking, I guess my question is: what must be done to ensure something allocated with 'new' will be a candidate for auto-collection later (when GC is enabled)?
Re: Mem Mgmt: With & Without the GC
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote: 1) If using the GC, but for whatever reason, I need to free something _right now_, is core.GC.free() the proper way to do this? The main problem is that `new` does not necessarily give you a pointer to the start of an allocation, and `GC.free()` does not work if you give it a pointer to the interior of an allocated block. You could use `GC.addrOf()` to get the base address from an interior pointer, but I don't know whether there could be other objects/arrays sharing the same memory block. If you explicitly allocated the memory block yourself with `GC.malloc()` then you have full control over what is placed in it and can safely `GC.free()` the memory using the base address. Keep in mind, `GC.free()` does not call finalisers.
Re: Thread affinity?
On Wednesday, 4 December 2013 at 23:23:51 UTC, Rob T wrote: On Wednesday, 4 December 2013 at 08:38:12 UTC, qznc wrote: You should file an issue [0] as this should actually be in core.thread. [0] https://d.puremagic.com/issues/enter_bug.cgi I filed an enhancement request for the thread module. Digging deeper, I notice that module core.sys.posix.pthread is missing the affinity related functions, so I'll file that as a bug. --rt :( https://issues.dlang.org/show_bug.cgi?id=11686
Re: Mem Mgmt: With & Without the GC
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote: 5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to? While my earlier suggestion of using malloc/emplace is one option, another is to use `GC.addRoot(objPtr)`. It ensures the object is never deallocated until you call `GC.removeRoot(objPtr)`.
Re: Mem Mgmt: With & Without the GC
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote: 2) Does calling object.destroy() mean that the object is marked for future collection? If not, how can I ensure it is properly marked. Because the GC is not of the incremental type, it can't perform any marking outside of a stop-the-world mark/sweep cycle. Instead, what `destroy()` does is finalise an object: that is, runs any destructors and puts it in an invalid state — in particular, all pointers contained within the object are nullified, so it doesn't reference any other objects. When I say 'object' I mean anything; class instance, structure, array, primitive, whatever.
Re: Mem Mgmt: With & Without the GC
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote: 6) If the GC is off, how is allocation/deallocation handled? Can I still use new for example (and how do I dealloc)? All the allocation/deallocation functionality is the same as normal, except the GC won't start a collection cycle unless it's out of memory. You can still use `free()` to deallocate, and it will free memory straight away.
Re: Mem Mgmt: With & Without the GC
On Sunday, 21 August 2016 at 16:14:53 UTC, Zane wrote: 5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to? I can answer this at least, If you don't want the GC to ever collect the object itself, here's the best way: Allocate the object with a non-GC allocator (such as std.c.malloc ), then use `emplace` to construct the object in that memory ( http://dlang.org/phobos/std_conv.html#.emplace ).
Mem Mgmt: With & Without the GC
Hey all, My knowledge of GCs is limited, but my faith in them (for most applications) has greatly increased with advances (like with Golang's recent updates). I am now trying to get a better sense for the direction D is going regarding memory management, both in relation to the GC and without it. Excuse my ignorance, but can someone clarify the following for me? 1) If using the GC, but for whatever reason, I need to free something _right now_, is core.GC.free() the proper way to do this? 2) Does calling object.destroy() mean that the object is marked for future collection? If not, how can I ensure it is properly marked. 3) How can I mark a non-object for future collection? For example, a dynamic array: int[] a = new int[10];. Do I just set any references to null? 4) What if I want to immediately deallocate a dynamically allocated non-object (such as the dynamic array) - Can I use core.GC.free? 5) Is there a way to do simple heap allocation with 'new' while ensuring the GC doesn't deallocate until I want it to? 6) If the GC is off, how is allocation/deallocation handled? Can I still use new for example (and how do I dealloc)? Thank you for any help you can provide.
Re: Is it's possible to install DMD/LDC/GDC on CoreOS?
On Sunday, 21 August 2016 at 15:25:59 UTC, David Nadlinger wrote: On Sunday, 21 August 2016 at 14:57:15 UTC, Seb wrote: An alternative would be to compile your application locally, then copy it over to your container. I don't know how similar CoreOs to a typical Linux distribution is, but if it comes with the typical shared libraries (libm.so, libc.so, lipthread.so), this should be possible ;-) LDC also allows you to create fully statically linked executables (-static). It allows you to sidestep issues with shared library version incompatibilities, but of course there has been a few technical issues and lot more politicking regarding fully statically linked executables on Linux. — David Oh I totally forgot about this, despite I think it's a great feature. Btw @Suliman fully static linking with LDC is used for the DLang Tour, which is built with Vibe.d and deployed using a docker container (based on busybox). Maybe that's worth looking at: https://github.com/stonemaster/dlang-tour/blob/master/Dockerfile https://github.com/stonemaster/dlang-tour/blob/master/dub.sdl https://github.com/stonemaster/dlang-tour/blob/master/.travis.yml (it adds a bit more, because the dockerized DLang Tour runs docker containers for each run)
Re: Is it's possible to install DMD/LDC/GDC on CoreOS?
On Sunday, 21 August 2016 at 14:57:15 UTC, Seb wrote: An alternative would be to compile your application locally, then copy it over to your container. I don't know how similar CoreOs to a typical Linux distribution is, but if it comes with the typical shared libraries (libm.so, libc.so, lipthread.so), this should be possible ;-) LDC also allows you to create fully statically linked executables (-static). It allows you to sidestep issues with shared library version incompatibilities, but of course there has been a few technical issues and lot more politicking regarding fully statically linked executables on Linux. — David
Re: Is it's possible to install DMD/LDC/GDC on CoreOS?
On Sunday, 21 August 2016 at 11:38:09 UTC, Suliman wrote: I would like to create small VPS instance with Linux distrib on VPS. Can I use CoreOS as image? Would it possible to install dlang there? An alternative would be to compile your application locally, then copy it over to your container. I don't know how similar CoreOs to a typical Linux distribution is, but if it comes with the typical shared libraries (libm.so, libc.so, lipthread.so), this should be possible ;-)
Re: Is it's possible to install DMD/LDC/GDC on CoreOS?
On Sunday, 21 August 2016 at 11:38:09 UTC, Suliman wrote: I would like to create small VPS instance with Linux distrib on VPS. Can I use CoreOS as image? Would it possible to install dlang there? For LDC, you can just download the latest release from https://github.com/ldc-developers/ldc/releases and you are good to go. Just make sure you have "gcc" available on your system for linking. — David
Is it's possible to install DMD/LDC/GDC on CoreOS?
I would like to create small VPS instance with Linux distrib on VPS. Can I use CoreOS as image? Would it possible to install dlang there?
Re: Rebind template
On Sunday, 21 August 2016 at 00:06:07 UTC, Engine Machine wrote: On Saturday, 20 August 2016 at 22:21:00 UTC, ag0aep6g wrote: On 08/21/2016 12:11 AM, Engine Machine wrote: Is there a way to rebind the arguments of a template? template foo(X) { // X is like A!(a,b,c) Y = Rebind!(X,d,e,f); // Y is like A!(d,e,f); } foo(A!(a,b,c)); ? template Rebind(alias instance, newArgs...) { import std.traits: TemplateOf; alias tmpl = TemplateOf!instance; alias Rebind = tmpl!newArgs; } This doesn't work because the rebound type is of type tmpl and not the original e.g., Rebind!(T!b, a) is tmpl!a not T!a. You are wrong. tmpl is just alias of template T. So tmpl!a and T!a are the same type. alias X = T!(int, short, char); alias Y = Rebind!(X, short, char, int); static assert(is(Y == T!(short, char, int))); // passes