Re: Is D suitable for my latest project?
On Sunday, 6 September 2015 at 14:36:53 UTC, chris stevens wrote: Hi All, I am considering using D for my latest project and there are a few features I would like and am not entirely sure at this point whether D has them. They are: - dynamic creation of classes/structs at runtime (think I can emulate this with variants/dynamic) At runtime, no. However... if it doesn't actually need to be runtime and is in the code itself you can have code be generated at compile time. - dynamic compilation of code files at runtime Only by running a compiler. But as above, if it doesn't strictly have to be at runtime and everything is specified in the source files, you can compute strings at compile-time and mix them in to generate code. - some basic code creation tools mixin, template mixin, CTFE. Are the above possible? It really depends on what you want to do. A lot of the dynamic code generation that goes on is done at runtime because that's what other languages support. In my experience a lot of those use-cases can be done at compile-time in D. A famous example is compile-time regular expressions. Unless you're writing a tool similar to grep, all regexes in your program are known at compile-time. They don't _need_ to be parsed/interpreted/compiled at run-time, that's just what every other language that isn't D does. So, if your use-case depends on information from the file-system, user interaction, networking, etc. then your only choice is to generate text files with D code and compile it. If, on the other hand, it's all defined by the code you write, then D has excellent compile-time code generation tools at your disposal. Atila
Re: What is "FilterResult" type?
On Wednesday, 9 September 2015 at 07:19:06 UTC, Bahman Movaqar wrote: On Tuesday, 8 September 2015 at 18:45:33 UTC, Jonathan M Davis wrote: If you're returning a range, you should be returning auto. @Jonathan, @cym13 and @Meta It's reasonable to use `auto`. However there are times when you need to pass the `auto` value to another function and the receiving function needs to know the type of its input arguments. No, it doesn't. It needs to know what the compile-time interface is, i.e. what it can do with that type. If the type in question happens to be an InputRange, then the consumer function would be: void func(R)(R range) if(isInputRange!R) { ... } instead of using a concrete type like this: void func(MyType range) { ... } That way you can change range types and `func` doesn't care. Atila
Re: Why 1f.iota(100f).array returns double[] not float[]?
On 09/08/2015 06:37 AM, Steven Schveighoffer wrote: I think this warrants a bug report, iota with only floats as parameters should result in floats. https://issues.dlang.org/show_bug.cgi?id=15033 Ali
Re: What's the "right" way to do openmp-style parallelism?
On Tue, 2015-09-08 at 07:33 +, Dominikus Dittes Scherkl via Digitalmars-d-learn wrote: > On Tuesday, 8 September 2015 at 05:50:30 UTC, Russel Winder wrote: > > void main() { > > immutable imax = 10; > > immutable jmax = 10; > > float[imax][jmax] x; > > foreach(int j; 1..jmax){ > > foreach(int i, ref item; parallel(x[j-1])){ > > x[j][i] = complicatedFunction(i, item); > > } > > } > > } > > > > (though sadly, this doesn't compile for a reason I can't fathom > > instantly) > Hmm. Shouldn't you instead parallel the outer loop? Can't do that because it is a pipeline: the current computation is input to the next one. As far as I can tell there is no way the code as presented can be parallelized in the general case. If there were some guarantees on complicatedFunction, then it is a different game. -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: class destruction
On Wednesday, 9 September 2015 at 07:19:58 UTC, Q wrote: Hi. I'm playing around with D for a while and I would like to switch. But here is one thing, I need an answer for. In the Docs is mentioned that it is not sure that the DTor of a class is called. But what if I have struct, which holds a C Handle which is destroyed as soon as the struct gets destroyed (more or less like a unique pointer) and I stick this struct into a class (because I strongly need polymorphism)? Then you have to make sure the class destruction happens and not rely on the GC. Can I be sure that the Handle is destroyed as soon as the class is destroyed? I think that yes, struct members are destroyed. But you need to make sure the class is destroyed. If so there are only two ways that come to mind: 1. the class holds only a pointer to the struct, which is unsafe since I must guarantee that the struct lives as long as the class 2. the class gets a close/finalize/destroy method (or is called with the built in destroy method), which is a absolute nogo, because it is absolutly sure that this can be forgotten. Besides, we live in 2015 and that is not C where I have to clean my code manually, so this option would be ridiculous :D I'm gratefull for any answers and ideas. I'm using the manual method after much hair-pulling: http://p0nce.github.io/d-idioms/#GC-proof-resource-class It absolutely is worse than the C++ situation, however with the above pattern leaks will be reported by the GC, which is a nice consolation prize. Alternatively, stick your class in Unique! / Refcounted! / scoped!
Re: What is "FilterResult" type?
On Wednesday, 9 September 2015 at 07:19:06 UTC, Bahman Movaqar wrote: The only way to make it work is `.array.idup` the output of `filter`. For example: auto result = reduce!( (acc, num) => acc.filter!( fb => (fb.x < num && fb.y < num) && (fb.x * fb.y > num) ).array.idup )(foobars, nums); Honestly, I cannot comprehend anything out of this; why I had to realise the lazy value and `idup` it for it to become usable by `reduce`? Does this mean that I am simply missing something obvious? Reduce takes the seed, calls your function, and your function returns a new seed. What is going wrong is that the types aren't the same. That is, the type of the seed you supplied - `typeof(foobars)` - isn't the type that your function returns - `typeof(acc.filter!...)`. `array()` fixes that, no idea why you need `idup()` though. OT: I wonder, is reduce able to call a different templated version of reduce?
Re: Is D suitable for my latest project?
On Tuesday, 8 September 2015 at 20:01:15 UTC, chris stevens wrote: Thanks for the reply Kagamin, just had a quick look at dparse and not sure how I could use it in the way you describe. Any examples of this? As I understand, you wanted to build an AST tree and format it to string?
Re: class destruction
On Wednesday, 9 September 2015 at 07:19:58 UTC, Q wrote: Besides, we live in 2015 and that is not C where I have to clean my code manually, so this option would be ridiculous :D The difference is that in C you need to manage POD memory too. Manual management of non-POD resources is a problem of a smaller size, and you can use RAII too.
Re: What is "FilterResult" type?
On Wednesday, 9 September 2015 at 07:19:06 UTC, Bahman Movaqar wrote: On Tuesday, 8 September 2015 at 18:45:33 UTC, Jonathan M Davis wrote: [...] @Jonathan, @cym13 and @Meta It's reasonable to use `auto`. However there are times when you need to pass the `auto` value to another function and the receiving function needs to know the type of its input arguments. In other news: Consider the following piece of code. *Please note that I am aware that the simple problem introduced can be solved in several ways which are more efficient.* immutable struct FooBar { int x; int y; } immutable(FooBar)[] foobars = [ FooBar(60, 100), FooBar(8, 20), FooBar(9, 15) ]; int[] nums = [20, 40, 55]; // // find FooBars which: // - x * y is greater than any `num` // - x and y are smaller than any `num` // auto result = reduce!( (acc, num) => acc.filter!( fb => (fb.x < num && fb.y < num) && (fb.x * fb.y > num) ) )(foobars, nums); // assert(result[0].x == 9 && result[0].y == 15); This fails to compile with the following message: Error: static assert "Incompatible function/seed/element: test.__unittestL40_4.__lambda1/immutable(FooBar)[]/int" /usr/include/dmd/phobos/std/algorithm/iteration.d(2518): instantiated from here: reduceImpl!(false, int[], immutable(FooBar)[]) /usr/include/dmd/phobos/std/algorithm/iteration.d(2502): instantiated from here: reducePreImpl!(int[], immutable(FooBar)[]) test.d(56):instantiated from here: reduce!(immutable(FooBar)[], int[]) The only way to make it work is `.array.idup` the output of `filter`. For example: auto result = reduce!( (acc, num) => acc.filter!( fb => (fb.x < num && fb.y < num) && (fb.x * fb.y > num) ).array.idup )(foobars, nums); Honestly, I cannot comprehend anything out of this; why I had to realise the lazy value and `idup` it for it to become usable by `reduce`? Does this mean that I am simply missing something obvious? You are using reduce in a weird way here... I find it normal to have to use weird internal tricks if you are trying weird things. The way I would have written it is: auto result = foobars.filter!(fb => nums.all!(n => (fb.x * fb.y) > n)) .filter!(fb => nums.all!(n => fb.x < n && fb.y < n)); Here you don't have any weird and completely unreadable reduce construct and don't have to realize the lazy check as std.algorithm.searching.all is lazy too.
Re: What is "FilterResult" type?
On Wednesday, 9 September 2015 at 07:59:57 UTC, Sebastiaan Koppe wrote: What is going wrong is that the types aren't the same. That is, the type of the seed you supplied - `typeof(foobars)` - isn't the type that your function returns - `typeof(acc.filter!...)`. Alright. So, `reduce` initial seed is an `array` while the output of `filter` is a `FilterResult`. I suppose it makes sense to realise it (`.array`) before passing to the next round. I was under the impression that `reduce` understands `FilterResult` and realises it internally; it doesn't and I was wrong. Though I believe it would have been more intuitive if it did. Thanks for the help. `array()` fixes that, no idea why you need `idup()` though. True --`idup` was not required. My mistake.
Re: What is "FilterResult" type?
On Tuesday, 8 September 2015 at 18:45:33 UTC, Jonathan M Davis wrote: If you're returning a range, you should be returning auto. @Jonathan, @cym13 and @Meta It's reasonable to use `auto`. However there are times when you need to pass the `auto` value to another function and the receiving function needs to know the type of its input arguments. In other news: Consider the following piece of code. *Please note that I am aware that the simple problem introduced can be solved in several ways which are more efficient.* immutable struct FooBar { int x; int y; } immutable(FooBar)[] foobars = [ FooBar(60, 100), FooBar(8, 20), FooBar(9, 15) ]; int[] nums = [20, 40, 55]; // // find FooBars which: // - x * y is greater than any `num` // - x and y are smaller than any `num` // auto result = reduce!( (acc, num) => acc.filter!( fb => (fb.x < num && fb.y < num) && (fb.x * fb.y > num) ) )(foobars, nums); // assert(result[0].x == 9 && result[0].y == 15); This fails to compile with the following message: Error: static assert "Incompatible function/seed/element: test.__unittestL40_4.__lambda1/immutable(FooBar)[]/int" /usr/include/dmd/phobos/std/algorithm/iteration.d(2518): instantiated from here: reduceImpl!(false, int[], immutable(FooBar)[]) /usr/include/dmd/phobos/std/algorithm/iteration.d(2502): instantiated from here: reducePreImpl!(int[], immutable(FooBar)[]) test.d(56):instantiated from here: reduce!(immutable(FooBar)[], int[]) The only way to make it work is `.array.idup` the output of `filter`. For example: auto result = reduce!( (acc, num) => acc.filter!( fb => (fb.x < num && fb.y < num) && (fb.x * fb.y > num) ).array.idup )(foobars, nums); Honestly, I cannot comprehend anything out of this; why I had to realise the lazy value and `idup` it for it to become usable by `reduce`? Does this mean that I am simply missing something obvious?
class destruction
Hi. I'm playing around with D for a while and I would like to switch. But here is one thing, I need an answer for. In the Docs is mentioned that it is not sure that the DTor of a class is called. But what if I have struct, which holds a C Handle which is destroyed as soon as the struct gets destroyed (more or less like a unique pointer) and I stick this struct into a class (because I strongly need polymorphism)? Can I be sure that the Handle is destroyed as soon as the class is destroyed? Or will the handle leak? If so there are only two ways that come to mind: 1. the class holds only a pointer to the struct, which is unsafe since I must guarantee that the struct lives as long as the class 2. the class gets a close/finalize/destroy method (or is called with the built in destroy method), which is a absolute nogo, because it is absolutly sure that this can be forgotten. Besides, we live in 2015 and that is not C where I have to clean my code manually, so this option would be ridiculous :D I'm gratefull for any answers and ideas.
C++ Interop -- Two Questions
Given a C++ class that looks like this: class Foo { static void Initialize(const SomeObject&); virtual void func1(); } The documentation at [1] doesn't say anything about how to handle static member functions like Initialize, nor do I see anything about references. I assume I can declare any reference function parameters using D's ref, but I have no idea how to declare static methods. My questions: 1) Am I right about ref? 2) Do I need to create a wrapper function in C or C++ for static member functions?
Re: Is D suitable for my latest project?
On Wednesday, 9 September 2015 at 08:24:06 UTC, Kagamin wrote: As I understand, you wanted to build an AST tree and format it to string? Thanks again. So I can build an AST and convert it to full D source from that? I think that's what i'm likely going need to do.
Re: C++ Interop -- Two Questions
On Wednesday, 9 September 2015 at 09:55:21 UTC, Mike Parker wrote: The documentation at [1] doesn't say anything about how to [1] http://dlang.org/cpp_interface.html
Re: Is D suitable for my latest project?
On Tuesday, 8 September 2015 at 21:51:03 UTC, wobbles wrote: "Previously undefined". As far as I know, this is impossible in D. Thr compiler has to know how much memory to allocate/request and it has to know that at compiletime (else it wouldn't be the compiler!) http://wiki.dlang.org/Dynamic_typing This is what I saw that made me think that I could. Have had another closer look and I do believe it's possible.
Re: What is "FilterResult" type?
On Wednesday, 9 September 2015 at 08:29:20 UTC, cym13 wrote: You are using reduce in a weird way here... Oh? Perhaps it was all because of the lame example I used :-) The real problem I was trying to solve, source of which I just pushed[1], was the `select` method on line 130. Is this idiomatic or still weird? The way I would have written it is: auto result = foobars.filter!(fb => nums.all!(n => (fb.x * fb.y) > n)) .filter!(fb => nums.all!(n => fb.x < n && fb.y < n)); For the lame example I gave, something similar occurred to me at first; but then I thought 4 `filter`s (assuming `all` is simply a `filter`) might be non-idiomatic as it might incur some performance penalty. Here you don't have any weird and completely unreadable reduce construct and don't have to realize the lazy check as std.algorithm.searching.all is lazy too. True. But is pumping the output of `filter` as the seed into `reduce` really considered weird usage!? [1] https://github.com/bahmanm/d-etudes/blob/master/source/e002/models.d
Re: Is D suitable for my latest project?
On Wednesday, 9 September 2015 at 09:14:30 UTC, Atila Neves wrote: So, if your use-case depends on information from the file-system, user interaction, networking, etc. then your only choice is to generate text files with D code and compile it. If, on the other hand, it's all defined by the code you write, then D has excellent compile-time code generation tools at your disposal. Thanks for the in depth reply. Unfortunately, yes, my use case depends on user input so definitions will not be known at compiletime. I'm keen to learn D though so I think I'm going to try and make it work with dynamically compiling and loading libraries.
Re: Is D suitable for my latest project?
On Tuesday, 8 September 2015 at 21:51:03 UTC, wobbles wrote: "Previously undefined". As far as I know, this is impossible in D. Thr compiler has to know how much memory to allocate/request and it has to know that at compiletime (else it wouldn't be the compiler!) There was also this: http://rosettacode.org/wiki/Add_a_variable_to_a_class_instance_at_runtime#D That made me think I could emulate the functionality I need.
Re: C++ Interop -- Two Questions
On 2015-09-09 11:55, Mike Parker wrote: Given a C++ class that looks like this: class Foo { static void Initialize(const SomeObject&); virtual void func1(); } The documentation at [1] doesn't say anything about how to handle static member functions like Initialize, nor do I see anything about references. I assume I can declare any reference function parameters using D's ref, but I have no idea how to declare static methods. My questions: 1) Am I right about ref? I would assume so. It's just a pointer under the hood. 2) Do I need to create a wrapper function in C or C++ for static member functions? The documentation for the C++ support is very outdated. I recommend to give it a try and see what happens :). Alternatively look in the DMD test suite and see what you can find, or the DMD source code now when it's in D. -- /Jacob Carlborg
Re: Is D suitable for my latest project?
On 09/08/2015 12:30 PM, chris stevens wrote: > create new > (previously undefined) classes in D at runtime that I could then use > with Object.factory to create instances of. SDC is a D compiler as a library but as far as I know, it's not complete yet: https://github.com/SDC-Developers/SDC Ali
Re: Why 1f.iota(100f).array returns double[] not float[]?
On Wednesday, 9 September 2015 at 06:37:17 UTC, Ali Çehreli wrote: https://issues.dlang.org/show_bug.cgi?id=15033 Ali https://github.com/D-Programming-Language/phobos/pull/3641
Re: What is "FilterResult" type?
On Wednesday, 9 September 2015 at 09:08:28 UTC, Atila Neves wrote: No, it doesn't. It needs to know what the compile-time interface is, i.e. what it can do with that type. If the type in question happens to be an InputRange, then the consumer function would be: void func(R)(R range) if(isInputRange!R) { ... } instead of using a concrete type like this: void func(MyType range) { ... } That way you can change range types and `func` doesn't care. Ah...makes sense. Thanks.
Re: C++ Interop -- Two Questions
Static functions are declared with `static` storage class. This looks so basic, it's even not documented in language spec, lol. In D classes are reference types by default.
Re: What is "FilterResult" type?
On Wednesday, 9 September 2015 at 11:30:26 UTC, Bahman Movaqar wrote: For the lame example I gave, something similar occurred to me at first; but then I thought 4 `filter`s (assuming `all` is simply a `filter`) might be non-idiomatic as it might incur some performance penalty. As those are templates I don't think you'd have any overhead ; I may be wrong about that but the whole point of such constructs is to allow what Walter poetically called “memory disallocation”. https://www.youtube.com/watch?v=znjesAXEEqw True. But is pumping the output of `filter` as the seed into `reduce` really considered weird usage!? I don't think it is really weird per se, I just can't think of a case where there isn't a better way to do it. I find it completely unreadable frankly, and I generally avoid reduce when I can because it is not UFCS-able. This is only personal opinion though.
Re: C++ Interop -- Two Questions
On Wednesday, 9 September 2015 at 11:49:33 UTC, Kagamin wrote: Static functions are declared with `static` storage class. This looks so basic, it's even not documented in language spec, lol. Yes, I get that. But how does that work when you're linking to a C++ library and the translation of the C++ class to D is an interface? Or is it possible now to link D classes directly with C classes? In D classes are reference types by default. Yes, of course. I just want to verify that the D ref and C++ ref are equivalent. I realize I can do it myself when I sit down this weekend and start exploring it, but I'm hoping someone can point me to a blog post, some sample code, or just give me some insights to save time.
Re: class destruction
But if others use my code they must think about finalizing the classes? That is very awkward. I'll take a look at Rust and otherwise I will stick with C++. Thanks for you answer. :)
Re: class destruction
On Wednesday, 9 September 2015 at 14:36:24 UTC, Q wrote: But if others use my code they must think about finalizing the classes? That is very awkward. classes, yes but structs, no. I'll take a look at Rust and otherwise I will stick with C++. Thanks for you answer. :) Well, resource management is only part of the story.
Re: class destruction
On Wednesday, 9 September 2015 at 15:32:58 UTC, Adam D. Ruppe wrote: On Wednesday, 9 September 2015 at 15:24:57 UTC, Q wrote: I thought that is not guaranteed, according to the docs? It is possible that the GC will never actually run, but you can force it to if you need it to by calling GC.collect at any time. Yes, but according to the specs it is not guaranteed that the GC calls the DTor if the Object is collected.
Re: Is D suitable for my latest project?
On Wednesday, 9 September 2015 at 10:23:55 UTC, chris stevens wrote: http://wiki.dlang.org/Dynamic_typing This is what I saw that made me think that I could. Have had another closer look and I do believe it's possible. These are things I wrote, so let me explain how they work: they do not attempt to actually run through the D compiler, but instead use tagged memory to check it all at runtime. This is kinda similar to creating a class, but it has no help from the compiler and no static type checks. So, let's say the user wanted to create an object with two integers, x and y. Code like the jsvar in the link does it with an associative array: var[string]. var is defined as a struct with a storage variable for the data, and a variable saying what type it is. All operations check that type variable. Then the names are indexed through the hash map. This is like how javascript engines work. You could also do it a bit differently by making a type definition for the whole object and allocating the memory that way. You can also go with the run the compiler and load a library option. There's different pros and cons for each approach. Here's some example code you might go with the second option: a type definition and dynamically allocated memory: --- struct ObjectHandle { immutable(ObjectDefinition) type; ubyte[] data; ubyte[] getRawDataForField(string field) { auto info = type.fields[field]; auto raw = data[info.offset .. info.offset + info.ti.tsize]; return raw; } string toString() { string s = type.name ~ "_dynamic(\n"; foreach(fieldName, fieldDefinition; type.fields) { s ~= "\t" ~ fieldName ~ ": " ~ typeToString(fieldDefinition.ti, getRawDataForField(fieldName)); s ~= "\n"; } return s ~ ")"; } } class ObjectDefinition { // OffsetTypeInfo is defined in object.d // http://dlang.org/phobos/object.html#OffsetTypeInfo // // These TypeInfo things are D's built-in runtime reflection. // We're borrowing that information and the types to create our // own extensions. OffsetTypeInfo[string] fields; string name; this(string name) { this.name = name; } void addField(string type, string name) { switch(type) { case "int": OffsetTypeInfo field; field.ti = typeid(int); field.offset = dataSize(); // you might also want to do some alignment here... fields[name] = field; break; // you can add other supported types here. You could even loop through a list // of them at compile time and generate this code btw. default: assert(0, "unsupported type " ~ type); } } int dataSize() const { int size = 0; foreach(k, v; fields) size += v.ti.tsize; return size; } // this is immutable because you don't want // the layout to change after you've created it. // // So it forces the factory to be called only after // the definition is set in stone. ObjectHandle factory() immutable { auto data = new ubyte[](this.dataSize()); // dynamically allocate space for our object's variables... foreach(k, field; fields) { // and now initialize them properly auto i = cast(const(ubyte)[]) field.ti.init(); if(i.length) data[field.offset .. field.offset + field.ti.tsize] = i[]; } return ObjectHandle(this, data); // and finally return it, along with a reference to this so we can identify the type later } } // Similarly to addField, doing operations on our field need to dispatch based on // type. I'll only show int. Others could be added in the if/else chain, or also // auto-generated by a compile time loop. string typeToString(const(TypeInfo) t, const(ubyte)[] rawData) { import std.conv; if(t == typeid(int)) { int i = *(cast(int*) rawData.ptr); return to!string(i); } return null; } void main() { auto definition = new ObjectDefinition("MyRuntimeType"); definition.addField("int", "x"); definition.addField("int", "y"); auto finalDefinition = cast(immutable) definition; definition = null; // we can't edit it anymore, so nulling out the mutable original reference auto object = finalDefinition.factory(); auto rawData = object.getRawDataForField("x"); rawData[0] = 15; // since I know it is an int, I can do
Re: class destruction
On Wednesday, 9 September 2015 at 14:57:26 UTC, Adam D. Ruppe wrote: On Wednesday, 9 September 2015 at 07:19:58 UTC, Q wrote: Can I be sure that the Handle is destroyed as soon as the class is destroyed? It will do that automatically. Like the others said, you won't be sure when the class is destroyed unless you have the user code take ownership of it. (This btw is the same as C++, just in C++ the ownership syntax is a wee bit shorter.) C++: class Foo { public: Foo() { /* acquire */ } ~Foo() { /* destroy */ } }; void useFoo(Foo* foo) { } // pretend I did the header separation here int main() { Foo foo; useFoo(); return 0; } D: -- module foo; class Foo { private this() { /* acquire */ } ~this() { /* destroy */ } } struct OwnedFoo(F) { F foo; alias foo this; ~this() { .destroy(foo); } @disable this(this) {} } auto create(F, T...)(T t) if(is(F : Foo)) { return OwnedFoo!F(new F(t)); } -- -- module main; import foo; void useFoo(Foo foo) {} void main() { auto foo = create!Foo(); } --- The code is a bit longer since the owned pointer in the standard library isn't exactly what I wanted, but you could use std.typecons.Unique too. (Actually, it does offer a bit more safety in reference escaping than mine. But mine is the closest to C++ default). The private constructor means it won't let you bypass the owned factory when creating it. A bit extra code in foo means all uses of it will be simple like in main. Just don't store the reference after it is destroyed, just like you would need to be careful with in C++. Using the library Unique will help you get this right too if you want to learn that. But in C++, classes and structs are value types _and_ extendable.There is no pressure to heap allocate a class. Of course, if I do that, I use a unique_ptr (shared_ptr is almost everytime misplaced). But since D has a GC and (per default) force to heap allocate a class. So IMO the GC should also destroy it, everything else is just awkward. I don't want to hack around in a new language. I think Rust offers my all I want. But thanks for the explanation.
Re: class destruction
And sorry if that sounds rude, I'm just in a hurry. I just think D is not mature enough for serious stuff. :) That is of course only my personal opinion.
Re: class destruction
On Wednesday, 9 September 2015 at 15:24:57 UTC, Q wrote: I thought that is not guaranteed, according to the docs? It is possible that the GC will never actually run, but you can force it to if you need it to by calling GC.collect at any time.
Re: class destruction
On Wednesday, 9 September 2015 at 15:37:50 UTC, Q wrote: Yes, but according to the specs it is not guaranteed that the GC calls the DTor if the Object is collected. Where? This page says pretty plainly: http://dlang.org/class.html#destructors "The garbage collector calls the destructor function when the object is deleted." (this is arguably a mistake, dtor and finalizer being the same thing have been a problem before, but it does say that) This sentence: "The garbage collector is not guaranteed to run the destructor for all unreferenced objects. " is because the GC is conservative and has a few exceptions in what it covers. But if you aren't one of those exceptions (data segment, or pinned by a false pointer (very rare in 64 bit btw), it will be collected and if it is collected, the dtor is run.
Re: class destruction
On Wednesday, 9 September 2015 at 15:37:50 UTC, Q wrote: Yes, but according to the specs it is not guaranteed that the GC calls the DTor if the Object is collected. Note that I believe this is the same as in Java (though not C#, interestingly enough). In Java an object's destructor is not guaranteed to run.
Re: C++ Interop -- Two Questions
On Wednesday, 9 September 2015 at 13:17:53 UTC, Mike Parker wrote: Yes, I get that. But how does that work when you're linking to a C++ library and the translation of the C++ class to D is an interface? Or is it possible now to link D classes directly with C classes? Classes and templates except for special members (which are usually relied upon heavily in C++ code, but maybe your C++ code is unusual). I realize I can do it myself when I sit down this weekend and start exploring it, but I'm hoping someone can point me to a blog post, some sample code, or just give me some insights to save time. You can see bugzilla issues marked with C++ keyword. The docs were deemed unworthy because of skills required to write C++ bindings. Maybe because it's still not practical as it doesn't support critical C++ idioms like RAII.
Re: class destruction
On Wednesday, 9 September 2015 at 07:19:58 UTC, Q wrote: Can I be sure that the Handle is destroyed as soon as the class is destroyed? It will do that automatically. Like the others said, you won't be sure when the class is destroyed unless you have the user code take ownership of it. (This btw is the same as C++, just in C++ the ownership syntax is a wee bit shorter.) C++: class Foo { public: Foo() { /* acquire */ } ~Foo() { /* destroy */ } }; void useFoo(Foo* foo) { } // pretend I did the header separation here int main() { Foo foo; useFoo(); return 0; } D: -- module foo; class Foo { private this() { /* acquire */ } ~this() { /* destroy */ } } struct OwnedFoo(F) { F foo; alias foo this; ~this() { .destroy(foo); } @disable this(this) {} } auto create(F, T...)(T t) if(is(F : Foo)) { return OwnedFoo!F(new F(t)); } -- -- module main; import foo; void useFoo(Foo foo) {} void main() { auto foo = create!Foo(); } --- The code is a bit longer since the owned pointer in the standard library isn't exactly what I wanted, but you could use std.typecons.Unique too. (Actually, it does offer a bit more safety in reference escaping than mine. But mine is the closest to C++ default). The private constructor means it won't let you bypass the owned factory when creating it. A bit extra code in foo means all uses of it will be simple like in main. Just don't store the reference after it is destroyed, just like you would need to be careful with in C++. Using the library Unique will help you get this right too if you want to learn that.
Re: class destruction
On Wednesday, 9 September 2015 at 15:10:33 UTC, Q wrote: But since D has a GC and (per default) force to heap allocate a class. So IMO the GC should also destroy it, everything else is just awkward. Well, it *does* by default. If that's what you want, just do it the plain way with simple `new`. It will be destroyed (and any structs inside also destroyed) when the GC gets it.
Re: class destruction
On Wednesday, 9 September 2015 at 15:19:04 UTC, Adam D. Ruppe wrote: On Wednesday, 9 September 2015 at 15:10:33 UTC, Q wrote: But since D has a GC and (per default) force to heap allocate a class. So IMO the GC should also destroy it, everything else is just awkward. Well, it *does* by default. If that's what you want, just do it the plain way with simple `new`. It will be destroyed (and any structs inside also destroyed) when the GC gets it. I thought that is not guaranteed, according to the docs?
Re: What is the difference between D and C++ regarding Unique, RefCounted and Scoped?
On Wednesday, 9 September 2015 at 20:17:44 UTC, cym13 wrote: This is subtly missing the main question: isn't C++-like memory management of D classes possible with Unique, RefCounted and Scoped? - Unique C++ has move semantics which make moves explicit. D's Unique is more like the deprecated C++'s auto_ptr: it has an opAssign overload that changes the owner. - RefCounted Only for D structs. std::shared_ptr works for all.
Re: friends with phobos, workaround?
On Wednesday, 9 September 2015 at 20:19:44 UTC, Daniel N wrote: For the record, I think D made the right decision... omitting friends. However there's one case in particular which I find useful, anyone see a good workaround for this? #include class Friendly { private: int val; Friendly(int&& val) : val(val) {} friend std::unique_ptr std::make_unique(int&& val); }; int main() { auto yay = std::make_unique(1); auto nay = new Friendly(1); } How about using a mixin template(http://dlang.org/template-mixin.html)? module makeunique; mixin template MakeUnique(Args...) { import std.typecons : Unique; static Unique!(typeof(this)) makeUnique(Args args) { return Unique!Friendly(new typeof(this)(args)); } } module friendly; import makeunique; struct Friendly { private: int val; this(int val) { this.val = val; } public: mixin MakeUnique!(int); }; module app; import std.stdio; import std.typecons; import friendly; void main() { auto yay = Friendly.makeUnique(1); }
Re: using std.algorithm to find intersection of DateTime[][] arg
Couldn't you use setIntersection together with reduce? Doesn't seem like the most efficient solution, but its less typing and most likely will have no bugs.
friends with phobos, workaround?
For the record, I think D made the right decision... omitting friends. However there's one case in particular which I find useful, anyone see a good workaround for this? #include class Friendly { private: int val; Friendly(int&& val) : val(val) {} friend std::unique_ptr std::make_unique(int&& val); }; int main() { auto yay = std::make_unique(1); auto nay = new Friendly(1); }
using std.algorithm to find intersection of DateTime[][] arg
I have a DateTime[][] arg (actually my own date type, but that shouldnt matter). Ordered by time series ticker (eg a stock) and then the date. eg arg[0] might be the dates relating to IBM and arg[0][0] would be the date of the first point in IBM time series. I would like to find the intersection of the dates. so setIntersection(arg[0],arg[1],arg[2] .. arg[$-1]) except that I don't know how many series are in arg at compile time. what's the most efficient way to use Phobos to find these? (I could write a loop, but I am trying to learn how to use std.algorithm better).
Re: What is the difference between D and C++ regarding Unique, RefCounted and Scoped?
On Wednesday, 9 September 2015 at 20:17:44 UTC, cym13 wrote: This is subtly missing the main question: isn't C++-like memory management of D classes possible with Unique, RefCounted and Scoped? I understand the limitations you mentioned, but it I don't think it is a good idea to tell C++ programmers that they work the same, since they are quite different.
Re: ref parameter qualifier and static arrays
On Wednesday, 9 September 2015 at 20:18:57 UTC, Paul wrote: Is it possible to call a function like this... void foo(ref int[] anArray) ...with slices of static arrays? I thought I might be able to use [0..$-1] but to no avail - I get an error like this (which is confusing!): Note that the upper bound of the slice is exclusive - [0..$-1] is not the whole array but everthing except the last entry. To slice the whole array, you can use [0..$] or just write int[42] a; auto b = a[]; (ref int[] anArray) is not callable using argument types (int[]) I've modified the function declaration and used .ptr when calling it but it seems like a retrograde step for a modern language - although I suppose ref is pretty much the same thing. In practice I'm using arrays of structs (which are of various fixed sizes and known at compile time) that are currently global in scope - something that I'd like to avoid. I suppose I could just ask, what is the 'best' way to give access to variously sized static arrays between different modules? It is impossible to pass a rvalue as a reference (intended behaviour, afaik it is causes problems if the reference escapes from foo and outlasts the rvalue). There is a bug report about the strange error message somewhere in the bug tracker. Some time ago someone announced to implement passing rvalue as reference but it seems the PR was not merged for dmd 2.068. Workaround: use a temporary variable. instead of int[42] a; foo(a[]); write int[42] a; auto tmp = a[]; foo(tmp);
Re: ref parameter qualifier and static arrays
On Wednesday 09 September 2015 22:18, Paul wrote: > > Is it possible to call a function like this... > > void foo(ref int[] anArray) > > ...with slices of static arrays? I thought I might be able to use > [0..$-1] but to no avail - I get an error like this (which is > confusing!): > > (ref int[] anArray) is not callable using argument types (int[]) Slice expressions are not lvalues (can't take their addresses), so you can't pass them in ref parameters. You can store the slice in a variable and pass that: void f(ref int[] x) {} int[3] a; version(none) f(a[]); /* Nope, a[] is not an lvalue. */ int[] s = a[]; f(s); /* Ok, s is an lvalue. */ But if you want to pass slice expressions, then you probably don't need that ref. When you pass a slice (without ref), what's actually passed is a pointer and length. The contents are not copied. That means, when you alter an array element, the change will be done the original, even without ref: void f(int[] x) {x[0] = 1;} int[3] a = [0, 0, 0]; f(a[]); assert(a[0] == 1); /* passes */ ref would allow you to resize the original dynamic array: void f(ref int[] x) {x ~= 4;} int[] a = [1, 2, 3]; f(a); assert(a.length == 4); /* passes */ But there's no point in doing that to temporaries like slice expressions.
Re: What is the difference between D and C++ regarding Unique, RefCounted and Scoped?
On Wednesday, 9 September 2015 at 20:34:03 UTC, Ola Fosheim Grøstad wrote: On Wednesday, 9 September 2015 at 20:17:44 UTC, cym13 wrote: This is subtly missing the main question: isn't C++-like memory management of D classes possible with Unique, RefCounted and Scoped? I understand the limitations you mentioned, but it I don't think it is a good idea to tell C++ programmers that they work the same, since they are quite different. Hence my question: in what? (I assume you are talking about Unique RefCounted etc and not about classes).
Re: char[] ported from C to char[0] in the D core library
On Wednesday, 9 September 2015 at 16:59:09 UTC, Adam D. Ruppe wrote: That's typically right, but since this case does it in-place instead of pointed, the zero length array is most accurate. I didn't consider that the name is placed right after the struct. Thanks !
Re: What is "FilterResult" type?
On Wednesday, 9 September 2015 at 11:30:26 UTC, Bahman Movaqar wrote: On Wednesday, 9 September 2015 at 08:29:20 UTC, cym13 wrote: The way I would have written it is: auto result = foobars.filter!(fb => nums.all!(n => (fb.x * fb.y) > n)) .filter!(fb => nums.all!(n => fb.x < n && fb.y < n)); For the lame example I gave, something similar occurred to me at first; but then I thought 4 `filter`s (assuming `all` is simply a `filter`) might be non-idiomatic as it might incur some performance penalty. Note that this can easily be rewritten with only one `filter` and one `all`: auto result = foobars.filter!( fb => nums.all!( n => fb.x * fb.y > n && fb.x < n && fb.y < n));
char[] ported from C to char[0] in the D core library
The struct core.sys.linux.sys.inotify.inotify_event contains the field "char[0] name" which corresponds to "char name[]" in C. Why it has been translated to "char[0]" ? For me "char*" would have been more appropriate.
Re: char[] ported from C to char[0] in the D core library
On Wednesday, 9 September 2015 at 16:49:39 UTC, badlink wrote: The struct core.sys.linux.sys.inotify.inotify_event contains the field "char[0] name" which corresponds to "char name[]" in C. Why it has been translated to "char[0]" ? In that structure, the name is appended directly to the end of the data instead of pointed to. The size isn't known at compile time, so a zero-length placeholder is there instead. You'd access it by using the .ptr property and get the length out of the `len` field. For me "char*" would have been more appropriate. That's typically right, but since this case does it in-place instead of pointed, the zero length array is most accurate.
Re: OSX prompt limit
On Wednesday, 9 September 2015 at 01:35:26 UTC, Joel wrote: auto line = terminal.getline("your prompt: "); Huh, that should work unless your terminal is outrageously narrow or maybe output starting on the right side of the screen already. But I can't look much further without having a mac myself, could be a few other causes :(
Re: OSX prompt limit
Maybe you can try gnu readline instead: extern(C) char* readline(const(char)* prompt); pragma(lib, "readline"); pragma(lib, "curses"); void main() { auto line = readline("your line: "); import std.stdio, std.conv; writeln(to!string(line)); }
Re: What is the difference between D and C++ regarding Unique, RefCounted and Scoped?
On Wednesday, 9 September 2015 at 19:53:55 UTC, ponce wrote: Oops, posted by mistake. On Wednesday, 9 September 2015 at 19:48:00 UTC, cym13 wrote: Hi, I know C++ and D without being a C++ or D guru (I know way more about D though). When talking about memory management the problem of RAII is often mentioned along with the fact that classes use the GC. I know well the difference between structs and classes and don't want to talk about the GC here. It seems to me that just as one can manage his memory in C++ using unique_ptr, shared_ptr and basic RAII we can manage our memory using Unique, RefCounted and Scoped. My question is: what is possible in C++ that isn't in D? C++ only has a D struct equivalent so all destructors are called deterministically. It's the addition of classes that create the problems in D. C++ can also throw by value, something that D can't really do. C++ objects can be: - heap-allocated or not - have deterministic destructors or not - be polymorphic or not without much restrictions. If you find a way to have the equivalent of virtual functions and dynamic casts for structs, then all our problems are virtually solved and struct would be all we need. How come that we are getting memory debates at all on this matter if we can do the same thing? Because D has class objects as an addition, and people want to use them because they need both polymorphism and holding resources. This is a very common scenario. Not all objects need a destructor, but when one need to have a destructor called, this propagates the need for clean-up to its owner too. Hence, class objects that need deterministic destruction are very easy to come by in D programs. If there are differences is fixing them an option to have something to show to D detractors? There was a proposal to stop the GC from calling destructors, which didn't take. There was also proposals of RC classes.
Re: What is the difference between D and C++ regarding Unique, RefCounted and Scoped?
On Wednesday, 9 September 2015 at 20:05:06 UTC, ponce wrote: C++ only has a D struct equivalent so all destructors are called deterministically. It's the addition of classes that create the problems in D. C++ can also throw by value, something that D can't really do. C++ objects can be: - heap-allocated or not - have deterministic destructors or not - be polymorphic or not without much restrictions. If you find a way to have the equivalent of virtual functions and dynamic casts for structs, then all our problems are virtually solved and struct would be all we need. How come that we are getting memory debates at all on this matter if we can do the same thing? Because D has class objects as an addition, and people want to use them because they need both polymorphism and holding resources. This is a very common scenario. Not all objects need a destructor, but when one need to have a destructor called, this propagates the need for clean-up to its owner too. Hence, class objects that need deterministic destruction are very easy to come by in D programs. If there are differences is fixing them an option to have something to show to D detractors? There was a proposal to stop the GC from calling destructors, which didn't take. There was also proposals of RC classes. This is subtly missing the main question: isn't C++-like memory management of D classes possible with Unique, RefCounted and Scoped? I understand the limitations you mentioned, but it seems to me that we already have a way to use classes which deterministically calls the destructor and frees classes from most of the GC's limitations. If one wants them on the stack reserving memory and emplacing is easy too. How does that not answer rants from people wanting C++ back? (I won't hide that the other current thread on "class destructor" is at the origin of this one, but I think the topics are different enough to justify two threads)
ref parameter qualifier and static arrays
Is it possible to call a function like this... void foo(ref int[] anArray) ...with slices of static arrays? I thought I might be able to use [0..$-1] but to no avail - I get an error like this (which is confusing!): (ref int[] anArray) is not callable using argument types (int[]) I've modified the function declaration and used .ptr when calling it but it seems like a retrograde step for a modern language - although I suppose ref is pretty much the same thing. In practice I'm using arrays of structs (which are of various fixed sizes and known at compile time) that are currently global in scope - something that I'd like to avoid. I suppose I could just ask, what is the 'best' way to give access to variously sized static arrays between different modules?
What is the difference between D and C++ regarding Unique, RefCounted and Scoped?
Hi, I know C++ and D without being a C++ or D guru (I know way more about D though). When talking about memory management the problem of RAII is often mentioned along with the fact that classes use the GC. I know well the difference between structs and classes and don't want to talk about the GC here. It seems to me that just as one can manage his memory in C++ using unique_ptr, shared_ptr and basic RAII we can manage our memory using Unique, RefCounted and Scoped. My question is: what is possible in C++ that isn't in D? How come that we are getting memory debates at all on this matter if we can do the same thing? If there are differences is fixing them an option to have something to show to D detractors?
Re: char[] ported from C to char[0] in the D core library
On Wednesday, 9 September 2015 at 16:49:39 UTC, badlink wrote: The struct core.sys.linux.sys.inotify.inotify_event contains the field "char[0] name" which corresponds to "char name[]" in C. Why it has been translated to "char[0]" ? For me "char*" would have been more appropriate. It's a flexible array member [1], not a pointer. Changing it to `char*` would make it incompatible with the C functions using it. [1]: https://en.wikipedia.org/wiki/Flexible_array_member
Re: What is the difference between D and C++ regarding Unique, RefCounted and Scoped?
On Wednesday, 9 September 2015 at 19:48:00 UTC, cym13 wrote: Hi, I know C++ and D without being a C++ or D guru (I know way more about D though). When talking about memory management the problem of RAII is often mentioned along with the fact that classes use the GC. I know well the difference between structs and classes and don't want to talk about the GC here. It seems to me that just as one can manage his memory in C++ using unique_ptr, shared_ptr and basic RAII we can manage our memory using Unique, RefCounted and Scoped. My question is: what is possible in C++ that isn't in D? C++ only h How come that we are getting memory debates at all on this matter if we can do the same thing? If there are differences is fixing them an option to have something to show to D detractors?
Re: What is the difference between D and C++ regarding Unique, RefCounted and Scoped?
On Wednesday, 9 September 2015 at 20:37:40 UTC, cym13 wrote: Hence my question: in what? (I assume you are talking about Unique RefCounted etc and not about classes). I think you should just refer them to the relevant man pages. Explanations are just going to be confusing as they are different. You can compare for yourself: http://en.cppreference.com/w/cpp/memory http://en.cppreference.com/w/cpp/language/value_category http://dlang.org/phobos/std_typecons.html http://dlang.org/phobos/std_algorithm_mutation.html
Re: OSX prompt limit
On Wednesday, 9 September 2015 at 17:47:44 UTC, Adam D. Ruppe wrote: Maybe you can try gnu readline instead: extern(C) char* readline(const(char)* prompt); pragma(lib, "readline"); pragma(lib, "curses"); void main() { auto line = readline("your line: "); import std.stdio, std.conv; writeln(to!string(line)); } Thanks Adam. That works better than normal. Up and down don't work though.
Re: OSX prompt limit
On Wednesday, 9 September 2015 at 21:27:05 UTC, Joel wrote: Thanks Adam. That works better than normal. Up and down don't work though. There's another function called add_history for that. Readline is a pretty popular library (also GPL though, keep that in mind if you distribute your program, it must also be GPL if you use it) so you can find more info on the net: http://web.mit.edu/gnu/doc/html/rlman_2.html Basic thing is if you want to add it to history, call add_history(ptr_it_returned); and it will then be available for up/down access. Also, readline is a C library, so it does expect you to free the memory it allocates too but you can probably just let that slide, it'll be fairly small leaks all things considered. If I can ever actually get access to a Mac, I'll try to debug my other lib on one too.