Re: dmd 2.068 deducing purity
On 8/25/15 1:05 PM, Jack Applegame wrote: On Tuesday, 25 August 2015 at 14:05:17 UTC, Steven Schveighoffer wrote: Can you post an example? import std.range; import std.algorithm; class Foo { int baz() {return 1;} void bar() { auto s = [1].map!(i = baz()); // compiles auto r = [1].map!(i = [1].map!(j = baz())); // Error: need 'this' for 'baz' of type 'int()' } } https://issues.dlang.org/show_bug.cgi?id=14962 -Steve
Re: [Dgame] Sprite loading and setting position in another class
Thank you for answering so quickly. If you don't mind me asking when will v0.7 be out? Not so soon. But maybe I'll release v0.6.5 with this feature at the end of september. For now you need to store your Texture in e.g. a Texture manager.
Re: [Dgame] Sprite loading and setting position in another class
On Tuesday, 25 August 2015 at 13:22:43 UTC, Namespace wrote: Edit: Basically my code is: //Texman.d// Class TextureManager { //variables void addSprite(string sprite_file, string name) { Surface wiki_img = Surface(sprite_file); Texture wiki_tex = Texture(wiki_img); sprite_list[name] = new Sprite(wiki_tex); sprite_list[name].setPosition(1,1); //tried to remedy by this } } You have to store your Texture. See My Sprite is only a white Rectangle on http://dgame-dev.de/index.php?controller=faq I'll change that with v0.7, so that Sprite will manage the Texture by himself. Thank you for answering so quickly. If you don't mind me asking when will v0.7 be out?
dmd 2.068 deducing purity
Using lambdas in 2.068 becomes painful: import std.algorithm; struct Foo { int baz(int v) { static int id; return v + id++; } void bar() { auto arr1 = [1, 2, 3]; auto arr2 = [4, 5, 6]; arr1.map!(i = arr2.map!(j = baz(i + j)) ); } } void main() { } Error: pure function 'bug.Foo.bar.__lambda1!int.__lambda1.__lambda2' cannot call impure function 'bug.Foo.baz' Also after switching to dmd 2.068 I got many stupid errors in lambdas (defined inside class non-static functions): Error: need 'this' for '...' of type '...' I have no idea how to fix it and had to go back to 2.067.
Re: __traits(allMembers) and aliases
On Tuesday, 25 August 2015 at 12:48:12 UTC, Dejan Lekic wrote: It is off-topic (sorry for that), but how you grab only those (say functions) in a module that are annotated with @ChoseMe ?? allMembers trait gives bunch of strings, and I could not find a way to use them with hasUDA template... Here's the actual implementation: ``` template isDerelictSymbol(alias SymbolContainer, string sym) { static if(is(typeof(hasUDA!(__traits(getMember, SymbolContainer, sym), DerelictSymbol { static if(hasUDA!(__traits(getMember, SymbolContainer, sym), DerelictSymbol)) enum isDerelictSymbol = true; else enum isDerelictSymbol = false; } else enum isDerelictSymbol = false; } ``` sym comes from allMembers. The typeof test probably isn't necessary in most cases, but function pointer aliases of this form: ``` extern(C) @nogc nothrow { alias FuncPtr = void funcPtr; } ``` ...fail to compile if I don't do the typeof check. If I can figure out a way to test for aliases, I can eliminate that bit as well.
Re: dmd 2.068 deducing purity
On 8/25/15 9:59 AM, Jack Applegame wrote: Using lambdas in 2.068 becomes painful: import std.algorithm; struct Foo { int baz(int v) { static int id; return v + id++; } void bar() { auto arr1 = [1, 2, 3]; auto arr2 = [4, 5, 6]; arr1.map!(i = arr2.map!(j = baz(i + j)) ); } } void main() { } Error: pure function 'bug.Foo.bar.__lambda1!int.__lambda1.__lambda2' cannot call impure function 'bug.Foo.baz' That seems like a bug, I see no pure in sight there, the compiler shouldn't infer pure if the inferred function is calling impure functions. Also after switching to dmd 2.068 I got many stupid errors in lambdas (defined inside class non-static functions): Error: need 'this' for '...' of type '...' I have no idea how to fix it and had to go back to 2.067. Can you post an example? -Steve
Re: NYT data article based on work of EMSI, who I think are a D shop
On Tuesday 25 August 2015 06:55, Laeeth Isharc wrote: http://www.nytimes.com/2015/08/23/magazine/the-creative-apocalypse-that-wasnt.html Interesting article as it corrects misconceptions of a few years back by looking at the data. This is based on tools from EMSI, who are a D shop. Congratulations to EMSI, and it would be great to hear more from them sometime about how they use D (I know they spoke at dconf once) This isn't really relevant to learning D. Did you mean to post to the general group?
Re: dmd 2.068 deducing purity
On Tuesday, 25 August 2015 at 14:05:17 UTC, Steven Schveighoffer wrote: Can you post an example? import std.range; import std.algorithm; class Foo { int baz() { return 1;} void bar() { auto s = [1].map!(i = baz()); // compiles auto r = [1].map!(i = [1].map!(j = baz())); // Error: need 'this' for 'baz' of type 'int()' } }
Re: __traits(allMembers) and aliases
On 26/08/15 12:06 AM, Mike Parker wrote: Is there a way to determine whether a given symbol is an alias? Consider this: ``` module funcs; alias FuncPtr = void function(); @ChooseMe FuncPtr funcPtr; alias anotherName = funcPtr; ``` Handing this module off to __traits(allMembers), then checking for the UDA on each member, I can filter out FuncPtr just fine. Unfortunately, anotherName passes the test, but I don't want it to. Is there anyway I can distinguish the anotherName alias from funcPtr without tagging it with a UDA? I can't find any sort of isAlias trait anywhere. I think a better way may be to check if it is a type or not. An alias appears as a type with the module being the one it is declared in. While my memory especially at 4am is rusty here: enum isVarDecl = __traits(compiles, {mixin(GOT ~ got;);}); Where GOT is assumed to be the string that you got from __traits(allMembers. It'll be true that it is a variable declaration. False for anything else e.g. a type.
Re: NYT data article based on work of EMSI, who I think are a D shop
On Tue, 25 Aug 2015 04:55:12 +, Laeeth Isharc wrote: http://www.nytimes.com/2015/08/23/magazine/the-creative-apocalypse-that- wasnt.html Interesting article as it corrects misconceptions of a few years back by looking at the data. This is based on tools from EMSI, who are a D shop. Congratulations to EMSI, and it would be great to hear more from them sometime about how they use D (I know they spoke at dconf once) Hi, I'm the Data group lead at EMSI; my group is the primary user of D in the organization and I can confirm that we are doing some interesting things with it that really leverage D's strengths. I will work on putting together a piece highlighting some of those things--any suggestions for venue? We don't have a public tech blog, so the wiki is the only thing coming to mind. P.S. Lots of other great mentions if you're interested in the work we do: http://www.economicmodeling.com/press/
Re: RAII and Deterministic Destruction
On Tuesday, 25 August 2015 at 22:35:57 UTC, Jim Hewes wrote: Although C++ can be ugly, one reason I keep going back to it rather then commit more time to reference-based languages like C# is because I like deterministic destruction so much. My question is whether D can REALLY handle this or not. I've not been sure about this for some time so now I'm just going to come out and finally ask. You may also find http://wiki.dlang.org/Memory_Management useful. It shows a number of different patterns one can employ for deterministic memory management. The one which you'll probably find most C++-like is http://wiki.dlang.org/Memory_Management#Explicit_Class_Instance_Allocation Mike
Re: Role of D in Python and performance computing [was post on using go 1.5 and GC latency]
On Tuesday, 25 August 2015 at 07:18:24 UTC, Ola Fosheim Grøstad wrote: On Tuesday, 25 August 2015 at 05:09:56 UTC, Laeeth Isharc wrote: On Monday, 24 August 2015 at 21:57:41 UTC, rsw0x wrote: [...] Horses for courses ? Eg for Andy Smith's problem of processing trade information of tens of gigs where Python was choking, I guess nobody in their right mind would use Rust. I don't think there is much difference between C, D or Rust in terms of computing. The core semantics are similar. With Rust you have the additional option of linear type checking. But Rust programmers of course want to use idiomatic linear typing as much as possible and that makes designing graph-like structures a challenge. An option implies you can turn it off, has this changed since the last time I used Rust?(admittedly, a while back) Memory safety doesn't seem like it's the top priority for scientific computing as much as fast turnarouds and performance... in my opinion, anyways.
Re: Trying to compile weather program
On Sunday, 23 August 2015 at 09:54:37 UTC, Tony wrote: auto loc = getJSON(ipinfo.io/)[loc] .str.split(,); BTW, the IP location doesn't work too reliably, if someone knows a better alternative...
Re: Role of D in Python and performance computing [was post on using go 1.5 and GC latency]
On Tuesday, 25 August 2015 at 05:09:56 UTC, Laeeth Isharc wrote: On Monday, 24 August 2015 at 21:57:41 UTC, rsw0x wrote: On Monday, 24 August 2015 at 21:20:39 UTC, Russel Winder wrote: For Python and native code, D is a great fit, perhaps more so that Rust, except that Rust is getting more mind share, probably because it is new. I'm of the opinion that Rust's popularity will quickly die when people realize it's a pain to use. Horses for courses ? Eg for Andy Smith's problem of processing trade information of tens of gigs where Python was choking, I guess nobody in their right mind would use Rust. I don't think there is much difference between C, D or Rust in terms of computing. The core semantics are similar. With Rust you have the additional option of linear type checking. But Rust programmers of course want to use idiomatic linear typing as much as possible and that makes designing graph-like structures a challenge.
Re: Role of D in Python and performance computing [was post on using go 1.5 and GC latency]
On Tuesday, 25 August 2015 at 07:21:13 UTC, rsw0x wrote: An option implies you can turn it off, has this changed since the last time I used Rust?(admittedly, a while back) Rust supports other reference types, so you decide by design whether you want to use linear typing or not?
Re: Digger 2.3 verstr.h problem
On 2015-08-24 14:27:52 +, Vladimir Panteleev said: Well, yes, your problem is that DMD 2.067 isn't finding a file while compiling DMD HEAD. So you would need to debug DMD 2.067 to find why it refuses to compile DMD HEAD. Any way that I can switch to 2.068 for building HEAD? Not that I expect to help a lot but who knows... And, any idea how I can print getcwd() during compile time? I tried but it's not working by using the function directly... this is really strange. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: Trying to compile weather program
On Tuesday, 25 August 2015 at 05:27:16 UTC, Tony wrote: I happened to notice that among my libcurl*s libcurl-gnutls.so.3 libcurl-gnutls.so.4 libcurl-gnutls.so.4.3.0 libcurl.so.3 libcurl.so.4 libcurl.so.4.3.0 none were just libcurl.so. So I made a link for libcurl.so to the latest version and now I am getting the same link errors I got after downloading the -dev version. So apparently my can't find -lcurl was because I didn't have a non-versioned libcurl.so available as it went away when I created one Yes, it's not particularly trivial to use libcurl currently, but thankfully all the libcurl complications will be gone in about 6 weeks with 2.069.0. https://github.com/D-Programming-Language/phobos/pull/3009 (and there was probably one created by the -dev download). Yes, the -dev packages come with unversioned symlinks and a pkg-config file (try `pkg-config --libs libcurl`).
Should this compile?
import std.stdio; import std.range : chain; auto test(string a) { return test(a, b); } auto test(string a, string b) { return chain(a, b); } void main() { writeln(test(a)); } Ends with: Error: forward reference to inferred return type of function call 'test' I know this exact sample is solvable by default parameter but there are cases where it is not possible. What to do then?
Re: Ranges - Question about desing choices
On Monday, 24 August 2015 at 17:59:00 UTC, Michal Minich wrote: Ok. What about this: there exactly the same 3 primitives as in D range, but popFront is requred to be called first, before calling front, or empty properties. Why current approach against this? Wouldn't that mean a null placeholder for the first popFront? That could be done though. However I'm not certain I understand what you wrote, do you mean that in foreach loops popFront would be called first or do you mean that each time you call front or empty the popFront method is called beforehand? I don't have much opinion about the former, but the later would be very problematic.
Re: C++/STL interop
On Monday 24 August 2015 17:37, anonymous wrote: I saw https://issues.dlang.org/show_bug.cgi?id=14956 . questions: - is std.basic_string released into the wild? - where do I find std.basic_string? - does std.vector exist? That would allow me to get rid of some C++ clue code (build an C-like interface, copy data etc)... basic_string and char_traits are C++ things. If you're looking for D bindings for them, I don't know if they exist or where to find them. You could try asking in the bugzilla issue you linked.
Re: Should this compile?
On Tuesday, 25 August 2015 at 18:19:40 UTC, tchaloupka wrote: import std.stdio; import std.range : chain; auto test(string a) { return test(a, b); } auto test(string a, string b) { return chain(a, b); } void main() { writeln(test(a)); } Ends with: Error: forward reference to inferred return type of function call 'test' I know this exact sample is solvable by default parameter but there are cases where it is not possible. What to do then? I think this is a bug, but is easily worked around with: auto test(string a) { return .test(a, b); } I suspect that the reason the error occurs, is that the auto return type automatically rewrites the function declaration into an eponymous template declaration. Since this creates a new naming scope, test by itself will only match the declaration inside the eponymous template. Forcing the compiler to look on the module level will force it to perform overload resolution.
Re: NYT data article based on work of EMSI, who I think are a D shop
On Tuesday, 25 August 2015 at 17:06:57 UTC, anonymous wrote: On Tuesday 25 August 2015 06:55, Laeeth Isharc wrote: http://www.nytimes.com/2015/08/23/magazine/the-creative-apocalypse-that-wasnt.html Interesting article as it corrects misconceptions of a few years back by looking at the data. This is based on tools from EMSI, who are a D shop. Congratulations to EMSI, and it would be great to hear more from them sometime about how they use D (I know they spoke at dconf once) This isn't really relevant to learning D. Did you mean to post to the general group? It seemed to me more relevant to the audience of those learning D (and therefore less committed to it) than those who already appreciate its value and have put in the effort required to master it. I didn't want to pollute the main list with something that I think is actually quite important, but that others may not. I'm open to being corrected about where the right place should be, but it wasn't an accidental decision to post here.
RAII and Deterministic Destruction
Although C++ can be ugly, one reason I keep going back to it rather then commit more time to reference-based languages like C# is because I like deterministic destruction so much. My question is whether D can REALLY handle this or not. I've not been sure about this for some time so now I'm just going to come out and finally ask. I know about this RAII section in the documentation: http://dlang.org/cpptod.html#raii But I don't believe that handles all cases, such as having classes as member variables of other classes. (Do the members get destructors called too?) Then there is std.typecons.Unique and std.typecons.RefCounted. With these, can I really get deterministic destruction for all cases like I would in C++? If so, it might be a good idea to emphasize this more in the documentation because I'd think people coming from C++ would be looking for this. Jim
Re: NYT data article based on work of EMSI, who I think are a D shop
Hi, I'm the Data group lead at EMSI; my group is the primary user of D in the organization and I can confirm that we are doing some interesting things with it that really leverage D's strengths. I will work on putting together a piece highlighting some of those things--any suggestions for venue? We don't have a public tech blog, so the wiki is the only thing coming to mind. P.S. Lots of other great mentions if you're interested in the work we do: http://www.economicmodeling.com/press/ Hi. Nice to 'meet' you. Maybe I'll become a client some day, although I am more focused on economies at a national than a regional level. I'll check out the PR shortly. The wiki is definitely a good start. The only problem with it as an ultimate way to present things is that people are inordinately impressed by slick and shiny presentation today, and as a company I would myself prefer to shape the context in which ideas are presented. So I like what John Colvin has done here with dlangscience: https://dlangscience.github.io/ Maybe there should be a simple portal for enterprise stories (and later it can be made glossier). For example, I was talking to someone who runs a $2bn startup fund recently about D, and I had nowhere to point him other than Andy Smith's presentation. D has some really good stories to tell on the enterprise front. They don't need any marketing BS to be convincing, but at the same time when you are explaining something you can't presume people know what you know, and have to walk people through things. Technical comparisons are nice, but stories speak to peoples' imagination and actually that's important in making decisions. On the wiki we have this as a start: http://wiki.dlang.org/Current_D_Use But it really could be made more vivid. I can't see there that at Facebook, in spite of their outstanding engineering talent, nobody had been able to speed up the preprocessor, but Andrei and Walter together using D were able to get this done quite quickly. Or the appeal of working with an agreeable language in attracting talent to a perhaps dull project (Andrei spoke about this wrt ODBC drivers, I think). I can help a bit with suggestions and some writing, but I don't have the time or ability to build this myself. This was really spurred by your question, and not quite an answer to it. So for that, maybe write the slides or narrative first, put up on wiki and then let's refine the presentation. Laeeth.
__traits(allMembers) and aliases
Is there a way to determine whether a given symbol is an alias? Consider this: ``` module funcs; alias FuncPtr = void function(); @ChooseMe FuncPtr funcPtr; alias anotherName = funcPtr; ``` Handing this module off to __traits(allMembers), then checking for the UDA on each member, I can filter out FuncPtr just fine. Unfortunately, anotherName passes the test, but I don't want it to. Is there anyway I can distinguish the anotherName alias from funcPtr without tagging it with a UDA? I can't find any sort of isAlias trait anywhere.
Static linking on Linux with dmd or gcc
Greetings! I'm just getting started with D, and just installed both dmd and gdc. Using the Hello, World program as an example, I'm trying to create a completely static / self-contained D binary. Using gdc, this is easy to do: gdc -static hello.d Then when I ldd hello, the system says: not a dynamic executable I can get this same result by creating a C++ program and running g++ -static. However, I can't seem to replicate this behavior with dmd, which I'd rather use than gdc. If I use the command: gdc -L-static It passes the -static flag to the linker, and not to gcc itself, so that doesn't work. If I use: dmd -v hello.d The generated gcc command is this: gcc hello.o -o hello -m64 -L/usr/lib/x86_64-linux-gnu -Xlinker --export-dynamic -l:libphobos2.a -lpthread -lm -lrt if I modify it to try to get it link statically, so that the command looks like this: gcc -static hello.o -o hello -m64 -L/usr/lib/x86_64-linux-gnu -Xlinker l:libphobos2.a -lpthread -lm -lrt I get this error: /usr/lib/x86_64-linux-gnu/libphobos2.a(sections_elf_shared_665_420.o): In function `_D2rt19sections_elf_shared11getTLSRangeFmmZAv': src/rt/sections_elf_shared.d:(.text._D2rt19sections_elf_shared11getTLSRangeFmmZAv+0x38): undefined reference to `__tls_get_addr' collect2: error: ld returned 1 exit status So basically, this Just Works (tm) when using gdc, but I simply cannot get it to work when using either dmd directly, or dmd to create the object file then using gcc to link. Is there anyway, using either dmd or dmd together with gcc, I can create a completely static binary like gdc can?
Re: Role of D in Python and performance computing [was post on using go 1.5 and GC latency]
On Monday, 24 August 2015 at 21:20:39 UTC, Russel Winder wrote: The issue here for me is that Chapel provides something that C, C++, D, Rust, Numba, NumPy, cannot – Partitioned Global Address Space (PGAS) programming. This directly attacks the multicore/multiprocessor/cluster side of computing, but not the GPGPU side, at least not per se. Yes, I agree that highly parallel batch programming requires a specialized approach. Though for most applications I think something like Pony will fit better. But they have to figure out how to do migration and load balancing I suppose. Javascript is moving towards programming using futures/promises, it is already built into Chrome. While that isn't actors per se, I think the computing objects approach will be more familiar for programmers over time and that will open up for actor-based languages too. Maybe.
Re: [Dgame] Sprite loading and setting position in another class
Edit: Basically my code is: //Texman.d// Class TextureManager { //variables void addSprite(string sprite_file, string name) { Surface wiki_img = Surface(sprite_file); Texture wiki_tex = Texture(wiki_img); sprite_list[name] = new Sprite(wiki_tex); sprite_list[name].setPosition(1,1); //tried to remedy by this } } You have to store your Texture. See My Sprite is only a white Rectangle on http://dgame-dev.de/index.php?controller=faq I'll change that with v0.7, so that Sprite will manage the Texture by himself.
Re: NYT data article based on work of EMSI, who I think are a D shop
On Wednesday 26 August 2015 00:22, Laeeth Isharc wrote: I'm open to being corrected about where the right place should be, but it wasn't an accidental decision to post here. I think you might find more interest over in General. Learn tends to be a question/answer kind of thing. So people probably don't come here to find articles. But I don't mean to play content police. I just thought you might have misclicked.
Re: dmd 2.068 deducing purity
On Tuesday, 25 August 2015 at 18:03:21 UTC, Steven Schveighoffer wrote: https://issues.dlang.org/show_bug.cgi?id=14962 -Steve Thanks.
Re: __traits(allMembers) and aliases
It is off-topic (sorry for that), but how you grab only those (say functions) in a module that are annotated with @ChoseMe ?? allMembers trait gives bunch of strings, and I could not find a way to use them with hasUDA template...
Re: [Dgame] Sprite loading and setting position in another class
On Tuesday, 25 August 2015 at 12:50:50 UTC, Jack wrote: So I've been using Dgame to learn about game development and I'm having an error when I'm trying to set a sprite's position initialized and stored in another class. Basically my code is: //Texman.d// Class Texman { //variables void addSprite(string sprite_file, string name) { Surface wiki_img = Surface(sprite_file); Texture wiki_tex = Texture(wiki_img); sprite_list[name] = new Sprite(wiki_tex); sprite_list[name].setPosition(1,1); //tried to remedy by this } } //GameObject.d class GameObject { Sprite sprite; float location_x; float location_y; //other variables void setLocation(float x, float y) { sprite.setPosition(x,y); location_x = x; location_y = y; } } //main.d/ void create() { wnd = Window(1024, 720, Dgame Test); sample_object = new GameObject(); texman = new TextureManager(); texman.addSprite(images.png, kirino); sample_object.setSprite(texman.getSprite(kirino)); sample_object.setLocation(500,500); } // And I'm having an error namely First-chance exception: core.exception.AssertError null pointing at the setLocation on GameObject.d. I tried to remove the setLocation method and tried to set Location on TextureManager itself and it worked. So is setting the position of a sprite outside of the class it initialized into forbidden, or am I doing something wrong here? Edit: Basically my code is: //Texman.d// Class TextureManager { //variables void addSprite(string sprite_file, string name) { Surface wiki_img = Surface(sprite_file); Texture wiki_tex = Texture(wiki_img); sprite_list[name] = new Sprite(wiki_tex); sprite_list[name].setPosition(1,1); //tried to remedy by this } }
[Dgame] Sprite loading and setting position in another class
So I've been using Dgame to learn about game development and I'm having an error when I'm trying to set a sprite's position initialized and stored in another class. Basically my code is: //Texman.d// Class Texman { //variables void addSprite(string sprite_file, string name) { Surface wiki_img = Surface(sprite_file); Texture wiki_tex = Texture(wiki_img); sprite_list[name] = new Sprite(wiki_tex); sprite_list[name].setPosition(1,1); //tried to remedy by this } } //GameObject.d class GameObject { Sprite sprite; float location_x; float location_y; //other variables void setLocation(float x, float y) { sprite.setPosition(x,y); location_x = x; location_y = y; } } //main.d/ void create() { wnd = Window(1024, 720, Dgame Test); sample_object = new GameObject(); texman = new TextureManager(); texman.addSprite(images.png, kirino); sample_object.setSprite(texman.getSprite(kirino)); sample_object.setLocation(500,500); } // And I'm having an error namely First-chance exception: core.exception.AssertError null pointing at the setLocation on GameObject.d. I tried to remove the setLocation method and tried to set Location on TextureManager itself and it worked. So is setting the position of a sprite outside of the class it initialized into forbidden, or am I doing something wrong here?
Re: [Dgame] Sprite loading and setting position in another class
Note that Texture is (in constrast to Sprite) a struct and not a class, so it is a value type. Dgame tries to use as many value types as possible to reduce the amount of garbage.
Re: Digger 2.3 verstr.h problem
On Tuesday, 25 August 2015 at 07:32:50 UTC, Robert M. Münch wrote: On 2015-08-24 14:27:52 +, Vladimir Panteleev said: Well, yes, your problem is that DMD 2.067 isn't finding a file while compiling DMD HEAD. So you would need to debug DMD 2.067 to find why it refuses to compile DMD HEAD. Any way that I can switch to 2.068 for building HEAD? Not that I expect to help a lot but who knows... You could try unpacking 2.068 and replacing the Digger/dl/dmd-2.067.1 directory. And, any idea how I can print getcwd() during compile time? I tried but it's not working by using the function directly... this is really strange. getcwd() doesn't work during compile time because it's a system call.
Re: RAII and Deterministic Destruction
On Tuesday, 25 August 2015 at 22:35:57 UTC, Jim Hewes wrote: Although C++ can be ugly, one reason I keep going back to it rather then commit more time to reference-based languages like C# is because I like deterministic destruction so much. My question is whether D can REALLY handle this or not. I've not been sure about this for some time so now I'm just going to come out and finally ask. I know about this RAII section in the documentation: http://dlang.org/cpptod.html#raii But I don't believe that handles all cases, such as having classes as member variables of other classes. (Do the members get destructors called too?) Then there is std.typecons.Unique and std.typecons.RefCounted. With these, can I really get deterministic destruction for all cases like I would in C++? If so, it might be a good idea to emphasize this more in the documentation because I'd think people coming from C++ would be looking for this. Jim Structs in D behave like in C++ - they are created on the stack (unless you use new or malloc), passed by value and are automatically destroyed at the end of the scope. All their members are destroyed recursively after the user defined destructor is called. Just try it out in a toy program and see if it works as you expect.
Re: RAII and Deterministic Destruction
On Wednesday, 26 August 2015 at 01:09:15 UTC, ZombineDev wrote: On Tuesday, 25 August 2015 at 22:35:57 UTC, Jim Hewes wrote: Although C++ can be ugly, one reason I keep going back to it rather then commit more time to reference-based languages like C# is because I like deterministic destruction so much. My question is whether D can REALLY handle this or not. I've not been sure about this for some time so now I'm just going to come out and finally ask. I know about this RAII section in the documentation: http://dlang.org/cpptod.html#raii But I don't believe that handles all cases, such as having classes as member variables of other classes. (Do the members get destructors called too?) Then there is std.typecons.Unique and std.typecons.RefCounted. With these, can I really get deterministic destruction for all cases like I would in C++? If so, it might be a good idea to emphasize this more in the documentation because I'd think people coming from C++ would be looking for this. Jim Structs in D behave like in C++ - they are created on the stack (unless you use new or malloc), passed by value and are automatically destroyed at the end of the scope. All their members are destroyed recursively after the user defined destructor is called. Just try it out in a toy program and see if it works as you expect. Classes on the other hand are reference types and are created on the garbage-collected heap by default (though you can do your own memory management). Similarly, structs created by new are also allocated on the GC heap. During collections the GC will call destructors, but it is not guaranteed and you should not rely on it. For example (depending on your GC usage and configuration) only a single collection may occur at the end of the program.
Re: RAII and Deterministic Destruction
On Tuesday, 25 August 2015 at 22:35:57 UTC, Jim Hewes wrote: Although C++ can be ugly, one reason I keep going back to it rather then commit more time to reference-based languages like C# is because I like deterministic destruction so much. My question is whether D can REALLY handle this or not. I've not been sure about this for some time so now I'm just going to come out and finally ask. I know about this RAII section in the documentation: http://dlang.org/cpptod.html#raii But I don't believe that handles all cases, such as having classes as member variables of other classes. (Do the members get destructors called too?) Then there is std.typecons.Unique and std.typecons.RefCounted. With these, can I really get deterministic destruction for all cases like I would in C++? If so, it might be a good idea to emphasize this more in the documentation because I'd think people coming from C++ would be looking for this. Jim Hi Jim. RAII in D is a common issue for people coming from C++. I don't know everything on the subject and would be glad to be corrected if I write a mistake but here is my share on the subject. There are two very different kind of objects in D and memory management is different for each: structs and classes. I think you mostly want to hear about classes, but I think each should be studied nonetheless. Structs: = Why would you use structs? - They are stack-allocated by default (but can be heap-allocated at will) - They are destroyed at the end of the scope, hence supporting RAII properly - They provide rather nice idioms for RAII [1] - They support single-inheritance through “alias this” - They support compile-time polymorphism through templates - They support complex object composition through template mixins [2] Why wouldn't you use structs? - You want to plug yourself on an already existing class-based system - You want to use interfaces - You need runtime-polymorphism Classes: = Why would you use classes? - They are heap-based and managed by the GC: lazy destruction - They provide full support for inheritance and OOP (including interfaces) - They support compile-time polymorphism through templates - They support complex object composition through template mixins [2] Why wouldn't use classes? - They are heap-based - They don't allow deterministic implicit destruction How to solve these problems? == Classes don't have *implicit* deterministic destruction but nothing prevents you from calling a destructor explicitely (be it ~this or another dedicated function). This can be easily done using scope(...) statements. If this is cumbersome, std.typecons.Unique and std.typecons.RefCounted can be used to provide a comportment analogous to that of modern C++. We said that structs are scope-based, a solution is to wrap an object into a struct and set the structs destructor to destroy the object as well at the end of the scope. std.typecons.scoped provides a nice wrapper arround this behaviour. The destruction of an object doesn't mean the destruction of the objects that it referenced. That can also be done explicitely. A word on the GC === I see a lot of C++ programmer who come to D with a single thought in mind: “Avoid the GC at all cost, let me manage my damn memory”. This is understandable, yet biaised. True, a GC isn't for all applications, but it has its place. Instead of fearing it, learning to use it well is important. One often doesn't need deterministic destruction. Lazy destruction has its benefits. I strongly advise not to rush trying to avoid the GC, instead profile profile profile. Conclusion === Doing RAII is possible for structs and for classes, but it is *really* easier with structs. D structs are really powerful and often underestimated by newcommers who rush on the class keyword. D classes aren't C++ classes. My advice would be to use structs as much as possible, to use classes where needed relying on the GC, and after profiling to introduce RAII behaviour into problematic classes. [1] https://w0rp.com/blog/post/an-raii-constructor-by-another-name-is-just-as-sweet/ [2] https://blog.dicebot.lv/posts/2015/08/OOP_composition_with_mixins
Re: RAII and Deterministic Destruction
On Tuesday, 25 August 2015 at 22:35:57 UTC, Jim Hewes wrote: Although C++ can be ugly, one reason I keep going back to it rather then commit more time to reference-based languages like C# is because I like deterministic destruction so much. My question is whether D can REALLY handle this or not. I've not been sure about this for some time so now I'm just going to come out and finally ask. I know about this RAII section in the documentation: http://dlang.org/cpptod.html#raii But I don't believe that handles all cases, such as having classes as member variables of other classes. (Do the members get destructors called too?) Then there is std.typecons.Unique and std.typecons.RefCounted. With these, can I really get deterministic destruction for all cases like I would in C++? If so, it might be a good idea to emphasize this more in the documentation because I'd think people coming from C++ would be looking for this. Jim To add to what the other people said, there exists scoped!T in std.typecons to allocate a class on the stack, and Unique/RefCounted as you mentioned. AFAIK refcounted is in the process of being overhauled, but the user should notice no differences.
Re: RAII and Deterministic Destruction
On Wednesday, 26 August 2015 at 01:18:43 UTC, ZombineDev wrote: On Wednesday, 26 August 2015 at 01:09:15 UTC, ZombineDev wrote: On Tuesday, 25 August 2015 at 22:35:57 UTC, Jim Hewes wrote: Although C++ can be ugly, one reason I keep going back to it rather then commit more time to reference-based languages like C# is because I like deterministic destruction so much. My question is whether D can REALLY handle this or not. I've not been sure about this for some time so now I'm just going to come out and finally ask. I know about this RAII section in the documentation: http://dlang.org/cpptod.html#raii But I don't believe that handles all cases, such as having classes as member variables of other classes. (Do the members get destructors called too?) Then there is std.typecons.Unique and std.typecons.RefCounted. With these, can I really get deterministic destruction for all cases like I would in C++? If so, it might be a good idea to emphasize this more in the documentation because I'd think people coming from C++ would be looking for this. Jim Structs in D behave like in C++ - they are created on the stack (unless you use new or malloc), passed by value and are automatically destroyed at the end of the scope. All their members are destroyed recursively after the user defined destructor is called. Just try it out in a toy program and see if it works as you expect. Classes on the other hand are reference types and are created on the garbage-collected heap by default (though you can do your own memory management). Similarly, structs created by new are also allocated on the GC heap. During collections the GC will call destructors, but it is not guaranteed and you should not rely on it. For example (depending on your GC usage and configuration) only a single collection may occur at the end of the program. Generally a very tutorial and reference is Ali's book [1], which is listed under Books and Articles in the sidebar of dlang.org. You should check the chapters Constructor and Other Special Functions [2] and Memory Management [3] (even though it covers mostly the GC). If you wish to avoid the GC, you can annotate your functions with the @nogc attribute [4] which enforces at compile-time that the annotated function won't use the GC. It is transitive which means that if you annotate your main() function with it, you shouldn't be allowed to use anything that allocates memory from the GC in your whole program. Since this feature was added there is an ongoing effort to minimize GC usage in the standard library, but there's still stuff that require it. That said the recommended approach is to build your data processing on ranges [5] (see the linked article by Andrei Alexandrescu) because it allows you to encapsulate memory usage more strategically. This is enabled by the lazy nature of ranges - they process data only when needed and so they don't need to allocate memory. Probably the best introduction to this technique is Walter Bright's keynote at DConf 2015 [6]: https://www.youtube.com/watch?v=znjesAXEEqw Be sure to check the DConf website as there's lots of great content from 2013 [7], 2014 [8] and 2015 [9]. [1]: http://ddili.org/ders/d.en/index.html [2]: http://ddili.org/ders/d.en/special_functions.html [3]: http://ddili.org/ders/d.en/memory.html [4]: http://dlang.org/attribute.html#nogc [5]: http://dlang.org/phobos/std_range.html [6]: https://www.youtube.com/watch?v=znjesAXEEqw [7]: http://dconf.org/2013/ [8]: http://dconf.org/2014/ [9]: http://dconf.org/2015/