Re: x.RC.__postblit () is not callable using argument types () const
On Tuesday, 5 February 2013 at 01:15:28 UTC, Dan wrote: I've seen these type of errors often and usually the cause kind of jumps out. In this case I'm totally confused. Just trying to move from 2.06 to 2.061. The code is: http://dpaste.dzfl.pl/f40e4d6f and fails with the error in subject line. Observations: - If static if(1) is changed to static if(0) it compiles - If either _valuationHistory or goo member of BSItem is commented out it compiles. I know the code is somewhat cryptic, but I've been using binary reduction comment in/out to try to narrow down this issue. I can not understand why an introduction of opEquals on a struct History with no relationship to RC causes an error to show for RC. Thanks Dan There is still problem with const structs vs. non-const postblit and destructor. In the past, the situation was even worse, but was partly fixed by laxing constness with respect to postblit and destructor. Now all such problems seems to come from associative array implementation in object.d
Re: x.RC.__postblit () is not callable using argument types () const
On Tuesday, 5 February 2013 at 04:03:06 UTC, Andrej Mitrovic wrote: Yeah, it's still not very helpful. And I have no idea where Slot comes from. This is sub struct inside object.AssociativeArray.
Re: x.RC.__postblit () is not callable using argument types () const
On Tuesday, 5 February 2013 at 11:51:40 UTC, Maxim Fomin wrote: On Tuesday, 5 February 2013 at 04:03:06 UTC, Andrej Mitrovic wrote: Yeah, it's still not very helpful. And I have no idea where Slot comes from. This is sub struct inside object.AssociativeArray. Is it the case that this is a D compiler (or library) problem and there is no issue with the code? Or is there really a problem with it that I am not seeing? I gather from the responses the code looks fine, otherwise any misunderstanding would come up quickly. I feel like I have painted myself in a corner a bit. I love D's templates and am a fan of the compile time reflection. I have mixins that support things like OpEquals, OpCmp, toHash, etc. I try very hard to work with const correctly. mixin template OpEquals() { bool opEquals(const ref typeof(this) other) const { return typesDeepEqual(this, other); } bool opEquals(const typeof(this) other) const { return typesDeepEqual(this, other); } } This OpEquals in the sample was just this signature (which I have mixed in all over successfully) but with a 'return true'. I think this is the correct signature to use. If I understand correctly, were I to remove the const, then const instances may no longer call it - which is not a good change. Transitive const is more than just simple const, and obviously more is better ;-). Since Slot is mentioned and object.AssociativeArrray it sounds like there may be a const-correctness issue with associative array itself rather than this code? Before the move to 2.061 I had to cast away const on const(V[K]) to get length and to iterate over them. But why the link between History!double and RC[int] when they are totally unrelated? Well, the only relation is their aggregation in BSItem. Baffling. Any suggestions appreciated. Thanks Dan
Re: x.RC.__postblit () is not callable using argument types () const
On Tuesday, 5 February 2013 at 15:06:47 UTC, Maxim Fomin wrote: The root of the problem is in: struct DAssociativeArray(Key, Value) { struct Slot { Value value; } } struct RC { this(this) { } } void main() { DAssociativeArray!(int, const(RC)) goo; } which doesn't compile (this is how Value[Key] is rewritten). I see - thanks. I assume it should compile and without the postblit it does. So - the original code is fine and there is a D problem with associative arrays. - Wouldn't the scenario be exactly the same without ValuationHistory? That is, if I comment out the member _valuationHistory, the goo member is not changed in structure at all, and yet it compiles just fine. - Does this mean that no one or very few developers store structs with postblits as value types in the standard associative array? Maybe I just do things differently than others. The way I see it you have to choose how you want to develop your structs/classes. I have chosen to use structs and templates and avoid classes, thinking this would greatly simplify things. Any struct needs to establish up front whether it will have value semantics or reference semantics. So far, I have preferred value semantics as data sharing leads to confusion. So if I have arrays in a struct I include postblits to provide value semantics. In another thread Walter made clear his distaste for postblits and preference for reference semantics coupled with copy on write semantics where needed. That approach, just does not seem worth it without more systematic support for COW. Assuming postblits are the issue, I don't understand why they are so hard to get right. Thanks Dan
Re: new T[size] vs .reserve - alloca
On 03/02/2013 13:22, bearophile wrote: Era Scarecrow: On Sunday, 3 February 2013 at 09:11:59 UTC, Namespace wrote: Sure, but alloca has the same ugly interface as malloc. :/ You mean that you have to specify how many raw bytes you want, then cast it to what you need? I never thought alloca or malloc were that ugly. The interface of alloca() is bug-prone. And it's not handy if you want to create a 2D or nD array on the stack :-) In bugzilla there is a preliminary request for better and less bug-prone VLAs for D. ^ I know you're aware of this, but maybe others might not know the default-argument alloca wrapping trick: import std.stdio; import core.stdc.stdlib:alloca; T *stack(T)(void* m = alloca(T.sizeof)) { return cast(T*)m; } void main(string[] args) { auto i = stack!int(); *i = 5; writeln(*i); writeln(i); int j; writeln(j); } More advanced behaviour e.g. switching to heap allocation for large sizes of T may be possible.
Re: x.RC.__postblit () is not callable using argument types () const
On Tuesday, 5 February 2013 at 15:49:59 UTC, Dan wrote: - Wouldn't the scenario be exactly the same without ValuationHistory? That is, if I comment out the member _valuationHistory, the goo member is not changed in structure at all, and yet it compiles just fine. Scenario is the same if there is struct with postblit and const(S) is passed as AA argument. If there is more code involved, the situation can be more complicated. - Does this mean that no one or very few developers store structs with postblits as value types in the standard associative array? Maybe I just do things differently than others. This does not imply such situation, simply there is a problem. You can workaround by struct DAssociativeArray(Key, Value) { struct Slot { Value value; } } struct RC { int i; void postblit() { i = -5; } this(this) const { void delegate() dg = postblit; dg(); } } void main() { RC rc1 = RC(5); RC rc2 = rc1; assert(rc2.i is -5); DAssociativeArray!(int, const(RC)) goo; }
Re: new T[size] vs .reserve - alloca
On 05/02/2013 16:17, Nick Treleaven wrote: On 03/02/2013 13:22, bearophile wrote: Era Scarecrow: On Sunday, 3 February 2013 at 09:11:59 UTC, Namespace wrote: Sure, but alloca has the same ugly interface as malloc. :/ You mean that you have to specify how many raw bytes you want, then cast it to what you need? I never thought alloca or malloc were that ugly. The interface of alloca() is bug-prone. And it's not handy if you want to create a 2D or nD array on the stack :-) In bugzilla there is a preliminary request for better and less bug-prone VLAs for D. ^ I know you're aware of this, but maybe others might not know the default-argument alloca wrapping trick: I've just realized this doesn't work for variable-length allocation: T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N)) Error: undefined identifier N, did you mean alias T? N is not visible in the caller's scope.
Re: new T[size] vs .reserve - alloca
Nick Treleaven: ^ I know you're aware of this, but maybe others might not know the default-argument alloca wrapping trick: For some usages it's an improvement over raw usage of alloca. I did see this in past, but sometimes I forget. Bye, bearophile
Re: new T[size] vs .reserve - alloca
On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote: On 05/02/2013 16:17, Nick Treleaven wrote: On 03/02/2013 13:22, bearophile wrote: Era Scarecrow: On Sunday, 3 February 2013 at 09:11:59 UTC, Namespace wrote: Sure, but alloca has the same ugly interface as malloc. :/ You mean that you have to specify how many raw bytes you want, then cast it to what you need? I never thought alloca or malloc were that ugly. The interface of alloca() is bug-prone. And it's not handy if you want to create a 2D or nD array on the stack :-) In bugzilla there is a preliminary request for better and less bug-prone VLAs for D. ^ I know you're aware of this, but maybe others might not know the default-argument alloca wrapping trick: I've just realized this doesn't work for variable-length allocation: T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N)) Error: undefined identifier N, did you mean alias T? N is not visible in the caller's scope. It does, just alias it. // import std.stdio; import core.stdc.stdlib:alloca; T* stack(T)(void* m = alloca(T.sizeof)) { return cast(T*)m; } T[] stack(T, alias N)(void* m = alloca(T.sizeof * N)) { return (cast(T*)m)[0 .. N]; } void main(string[] args) { int* p = stack!int(); int[] arr = stack!(int, 5)(); *p = 2; arr[0] = 5; writeln(*p); writeln(arr); } //
Re: x.RC.__postblit () is not callable using argument types () const
On Tuesday, 5 February 2013 at 16:36:16 UTC, Maxim Fomin wrote: This does not imply such situation, simply there is a problem. You can workaround by [snip] struct RC { int i; void postblit() { i = -5; } this(this) const { void delegate() dg = postblit; dg(); } } Great thanks. I'll try. But why does this even code work? I would have thought const guarantee would prevent calls to non-const postblit function. I was under impression this(this) const does not work - but maybe that has changed with 2.061. What source (lang spec, TDPL, or newsgroup) led you to this solution and for how long will it be valid? Where can I read more on it? Thanks Dan
Re: GtkD button size
On Monday, 4 February 2013 at 21:55:24 UTC, Mike Wey wrote: On 02/04/2013 03:03 PM, SaltySugar wrote: On Sunday, 3 February 2013 at 16:07:06 UTC, Artur Skawina wrote: On 02/03/13 16:53, SaltySugar wrote: GTKD. Can someone explain me how to change button size in vbox, hbox? setSizeRequest (70, 50); doesn't work. Thanks. Try playing with an interactive gui tool, such as glade. The fill, expand and size request interactions will be immediately visible. artur I'm waiting other answers :) A VBox or A HBox will always expand the Widget in the direction opposite of the on it's managing, if it expands the Widget in that direction depends on the options passed to packStart. So get the size request to work with those containers you'll have to wrap a HBox in a VBoc or visa versa. A more convenient container would be the ButtonBox which doesn't expand the Button in the direction it's not managing. And thus properly handles the size request. A Grid or Table might also apply depending on the complete layout. I can't find any tutorials about buttonboxes. Can you write how to use it?
Re: Allocating large 2D array in D
On Mon, Feb 04, 2013 at 04:58:36PM +0100, bearophile wrote: monarch_dodra: If all (but last of) the dimensions are known at compile time, then you can dynamically allocate an array of fixed sized arrays: // enum size_t gridSize = 4_000; enum size_t total = gridSize * gridSize; static assert (total == 16_000_000); //16 million doubles total static assert (total * double.sizeof == 128_000_000); //126 Megs allocated void main() { double[gridSize][] gridInfo = new double[gridSize][](gridSize); } // This will give you a dense array: Eg: all the data is contiguous in memory. Nice. This idiom should be added to the D docs. [...] Added to wiki: http://wiki.dlang.org/Dense_multidimensional_arrays T -- If Java had true garbage collection, most programs would delete themselves upon execution. -- Robert Sewell
Re: x.RC.__postblit () is not callable using argument types () const
On Tuesday, 5 February 2013 at 17:05:23 UTC, Dan wrote: But why does this even code work? I would have thought const guarantee would prevent calls to non-const postblit function. I was under impression this(this) const does not work - but maybe that has changed with 2.061. Forgot to mention, it works on 2.061. What source (lang spec, TDPL, or newsgroup) led you to this solution and for how long will it be valid? Where can I read more on it? Thanks Dan Const postblit worked at least at 2.060. Originally idea was to make const cast on function call, but at a current time it is not needed. May be another bug.
Re: Allocating large 2D array in D
H. S. Teoh: Added to wiki: http://wiki.dlang.org/Dense_multidimensional_arrays It contains: enum columns = 100; int rows = 100; double[gridSize][] gridInfo = new double[columns][](rows); gridSize is undefined. I suggest to write something like: enum nColumns = 100; int nRows = 120; double[nColumns][] matrix2 = new double[nColumns][](nRows); Bye, bearophile
Re: Allocating large 2D array in D
On Tue, Feb 05, 2013 at 07:38:40PM +0100, bearophile wrote: H. S. Teoh: Added to wiki: http://wiki.dlang.org/Dense_multidimensional_arrays It contains: enum columns = 100; int rows = 100; double[gridSize][] gridInfo = new double[columns][](rows); gridSize is undefined. [...] Oops, that was a typo. Fixed. P.S. Feel free to edit the page yourself if you see a mistake. That's what a wiki is for, after all. T -- I suspect the best way to deal with procrastination is to put off the procrastination itself until later. I've been meaning to try this, but haven't gotten around to it yet. -- swr
Re: GtkD button size
On 02/05/2013 06:33 PM, SaltySugar wrote: I can't find any tutorials about buttonboxes. Can you write how to use it? Here is a small example: import gtk.MainWindow; import gtk.Button; import gtk.Main; import gtk.HButtonBox; class Application : MainWindow { this() { super(GtkD App); setDefaultSize(200, 200); HButtonBox hBox = new HButtonBox(); Button btnLog = new Button(Login); btnLog.setSizeRequest (70, 50); hBox.packStart(btnLog, false, false, 3); add(hBox); showAll(); } } void main(string[] args) { Main.init(args); new Application(); Main.run(); } It looks like this: http://i45.tinypic.com/msivb4.png -- Mike Wey
Re: A little of coordination for Rosettacode
On 5-2-2013 0:55, bearophile wrote: Is the Fwend user of Rosettacode (or some other interested person) around here? I have written partial D implementations for three tasks, maybe a little of coordination will speedup the work: http://rosettacode.org/wiki/Permutations/Rank_of_a_permutation http://rosettacode.org/wiki/Universal_Turing_machine http://rosettacode.org/wiki/RCRPG I'll give it a shot if you like. The RCRPG I'd like to try first. By the way, I think 'Qznc' may want to have a look at 'The dining philosophers': http://rosettacode.org/wiki/Dining_philosophers
Re: GtkD button size
On Tuesday, 5 February 2013 at 19:31:01 UTC, Mike Wey wrote: On 02/05/2013 06:33 PM, SaltySugar wrote: I can't find any tutorials about buttonboxes. Can you write how to use it? Here is a small example: import gtk.MainWindow; import gtk.Button; import gtk.Main; import gtk.HButtonBox; class Application : MainWindow { this() { super(GtkD App); setDefaultSize(200, 200); HButtonBox hBox = new HButtonBox(); Button btnLog = new Button(Login); btnLog.setSizeRequest (70, 50); hBox.packStart(btnLog, false, false, 3); add(hBox); showAll(); } } void main(string[] args) { Main.init(args); new Application(); Main.run(); } It looks like this: http://i45.tinypic.com/msivb4.png Thank you, Mike. One more question. Can I use hbox.add(btn); instead of hbox.packStart (btn,false,false,5); What difference between them? Sorry, for my bad English.
Re: new T[size] vs .reserve - alloca
Why not: [code] T[] stack(T, const size_t N)(void* m = alloca(T.sizeof * N)) { return (cast(T*)m)[0 .. N]; } [/code] ?
Re: A little of coordination for Rosettacode
Jos van Uden: I'll give it a shot if you like. The RCRPG I'd like to try first. I have already partially written those: Partial translation of rcrpg-Python: http://codepad.org/SflrKqbT Partial translation of permutations_rank_of_a_permutation-Python: http://codepad.org/El9SQwOE Plus a better Perl implementation of the uniform() on BigInts: http://codepad.org/LGcMpk2f Partial translation of the universal_turing_machine-Ruby: http://codepad.org/nUXLzAg2 Bye, bearophile
Re: GtkD button size
On 2013-02-05 20:48, SaltySugar wrote: Can I use hbox.add(btn); instead of hbox.packStart (btn,false,false,5); What difference between them? Using add(btn) you would probably end up with a stretched button again. :) hbox.packStart(child, expand, fill, padding) It was explicitly said that expand = false, to prevent button resizing. Read more here: http://www.mono-project.com/GtkSharp:_Packing_with_Boxes It's Gtk# but may be of some help to you.
Re: A little of coordination for Rosettacode
On 5-2-2013 21:10, bearophile wrote: How do we avoid working on the same thing? Partial translation of rcrpg-Python: http://codepad.org/SflrKqbT Partial translation of permutations_rank_of_a_permutation-Python: http://codepad.org/El9SQwOE The 2 above, I could try. Plus a better Perl implementation of the uniform() on BigInts: http://codepad.org/LGcMpk2f My perl is too rusty. Partial translation of the universal_turing_machine-Ruby: http://codepad.org/nUXLzAg2 I'd have to first read up on the subject. Bye, bearophile
Re: new T[size] vs .reserve - alloca
On 05/02/2013 16:47, monarch_dodra wrote: On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote: I've just realized this doesn't work for variable-length allocation: T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N)) Error: undefined identifier N, did you mean alias T? N is not visible in the caller's scope. It does, just alias it. // import std.stdio; import core.stdc.stdlib:alloca; T* stack(T)(void* m = alloca(T.sizeof)) { return cast(T*)m; } T[] stack(T, alias N)(void* m = alloca(T.sizeof * N)) { return (cast(T*)m)[0 .. N]; } This works if you know N at compile-time. But there doesn't seem to be a way to wrap alloca to accept a runtime-only value, e.g.: // allocate as many ints as command-line parameters int[] arr = stack!int(args.length);
Re: new T[size] vs .reserve - alloca
On Tuesday, 5 February 2013 at 20:47:46 UTC, Nick Treleaven wrote: On 05/02/2013 16:47, monarch_dodra wrote: On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote: I've just realized this doesn't work for variable-length allocation: T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N)) Error: undefined identifier N, did you mean alias T? N is not visible in the caller's scope. It does, just alias it. // import std.stdio; import core.stdc.stdlib:alloca; T* stack(T)(void* m = alloca(T.sizeof)) { return cast(T*)m; } T[] stack(T, alias N)(void* m = alloca(T.sizeof * N)) { return (cast(T*)m)[0 .. N]; } This works if you know N at compile-time. But there doesn't seem to be a way to wrap alloca to accept a runtime-only value, e.g.: // allocate as many ints as command-line parameters int[] arr = stack!int(args.length); I don't have access to my compiler, but that *should*work. Did you try it? BTW, the syntax would be: int[] arr = stack!(int, args.length)();
Re: new T[size] vs .reserve - alloca
On 05/02/2013 21:02, monarch_dodra wrote: On Tuesday, 5 February 2013 at 20:47:46 UTC, Nick Treleaven wrote: On 05/02/2013 16:47, monarch_dodra wrote: T[] stack(T, alias N)(void* m = alloca(T.sizeof * N)) { return (cast(T*)m)[0 .. N]; } This works if you know N at compile-time. But there doesn't seem to be a way to wrap alloca to accept a runtime-only value, e.g.: // allocate as many ints as command-line parameters int[] arr = stack!int(args.length); I don't have access to my compiler, but that *should*work. Did you try it? BTW, the syntax would be: int[] arr = stack!(int, args.length)(); I've just tried it with dmd 2.059 (haven't upgraded yet). I got: Error: variable args cannot be read at compile time void main(string[] args) { int[] arr = stack!(int, args.length)(); }
Re: new T[size] vs .reserve - alloca
On 05/02/2013 21:13, Nick Treleaven wrote: I've just tried it with dmd 2.059 (haven't upgraded yet) sorry, 2.060
Re: GtkD button size
On 02/05/2013 08:48 PM, SaltySugar wrote: Thank you, Mike. One more question. Can I use hbox.add(btn); instead of hbox.packStart (btn,false,false,5); What difference between them? Sorry, for my bad English. hbox.add would call packStart with the defaults, witch would be packStart(btn, true, true, 0); Changing packStart to add in the small example i posted it appears to stay the same. -- Mike Wey
Re: new T[size] vs .reserve - alloca
On Tuesday, 5 February 2013 at 21:14:32 UTC, Nick Treleaven wrote: On 05/02/2013 21:13, Nick Treleaven wrote: I've just tried it with dmd 2.059 (haven't upgraded yet) sorry, 2.060 Right, it's alias being finicky, because args.length isn't an actual variable (it's a property). The problem is not so much that it can't be read at compile time, that the compiler doesn't know what to alias to. I'll file a bug report to try and see if we can't get a better message. Use a named variable, or use a manifest constant: // import std.stdio; import core.stdc.stdlib:alloca; T* stack(T)(void* m = alloca(T.sizeof)) { return cast(T*)m; } T[] stack(T, alias N)(void* m = alloca(T.sizeof * N)) { return (cast(T*)m)[0 .. N]; } void main(string[] args) { auto n = args.length; int[] arr = stack!(int, n)(); } //
Re: A little of coordination for Rosettacode
Jos van Uden: How do we avoid working on the same thing? With a little coordination :-) Partial translation of rcrpg-Python: http://codepad.org/SflrKqbT Partial translation of permutations_rank_of_a_permutation-Python: http://codepad.org/El9SQwOE The 2 above, I could try. Plus a better Perl implementation of the uniform() on BigInts: http://codepad.org/LGcMpk2f My perl is too rusty. That perl is meant as a part of permutations_rank_of_a_permutation. Feel free to search for other good algorithms to implement uniform(BigInt,BigInt) much better than me. If this code comes out good enough, it must be added to Phobos (and it's meant to be designed better than the Java uniform generator for its bigintegers, because it doesn't give a correct range). Partial translation of the universal_turing_machine-Ruby: http://codepad.org/nUXLzAg2 I'd have to first read up on the subject. It's a simple task, just to implement an universal Turing machine. It's a matter of finding a balance between the too much high level Ruby version and a too much C-like version. In D a simple way to implement a tape is with two dynamic arrays, one represents all the cells on the right to the starting position, and the other array is used inverted, to represent all the cells on the left of the right position. There are faster solutions, but this is enough for the purposes of Rosettacode. Bye, bearophile
Regarding isSorted
This used to print true-false, now prints true-true. Is this a bug? import std.stdio, std.algorithm; void main() { auto x = abcd; writeln(isSorted(x)); auto y = acbd; writeln(isSorted(y)); } Maybe this line: https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm.d#L9237 for (; !ahead.empty; ahead.popFront(), ++i) Should be: for (; !ahead.empty; ahead.popFront(), r.popFront(), ++i) Bye, bearophile
Re: Regarding isSorted
On Wednesday, February 06, 2013 01:33:29 bearophile wrote: This used to print true-false, now prints true-true. Is this a bug? import std.stdio, std.algorithm; void main() { auto x = abcd; writeln(isSorted(x)); auto y = acbd; writeln(isSorted(y)); } Maybe this line: https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm.d #L9237 for (; !ahead.empty; ahead.popFront(), ++i) Should be: for (; !ahead.empty; ahead.popFront(), r.popFront(), ++i) That definitely looks like a bug. acbd _isn't_ sorted. - Jonathan M Davis
Re: Regarding isSorted
Jonathan M Davis: That definitely looks like a bug. acbd _isn't_ sorted. OK. Thank you. http://d.puremagic.com/issues/show_bug.cgi?id=9457 Brad Anderson: Have a GitHub account, bearophile? Not yet, but probably I will have one. Just hit Edit at the top of that link you gave, make the change, and click Proposal File Change and it'll roll up a pull request. Should take less than a minute. I use this for almost every minor pull requests I do. The autotester takes care of the rest. Sounds quick easy. I will remember this. Thank you. Looks like line 9221 is essentially the same code so you may want to change that line too. Added in the bug report. Bye, bearophile
Re: best D way to port C style array of void*
On Tue, 05 Feb 2013 22:16:17 -0500, estew est...@gmail.com wrote: Hi All, I've some old C code which I'm porting to D. It's a learning exercise so I don't want to just wrap the C lib. I have an array of void* and an array of callbacks that take void* pointers for user data. I'm wondering what is a good way to port this into D and avoid the void*. My C++ version uses std::function for the callbacks and functors. I'm using std::vectorboost::any For the array of void*. Maybe it's not the best approach but it's my best efforts. For the D port I'd like to improve on the C++ approach and I'd love to know a better way to do it. * Could I replace the boost::any with an array of Variant from std.variant? That is probably what I would recommend. Although I would consider altering the design to avoid this. D has a much better type system than C or C++. * Can I assign a struct with opCall() to a function pointer, similar to how std::function can take a struct with an operator(). * Should I forget functors and use a callback that takes a std.variant (or whatever the boost::any like thing in D is) instead of void*? Use a delegate. A delegate is a function call with a context pointer. No need to specify the type of the pointer, it's whatever type it needs to be. You can create a delegate just about anywhere. It can be a member function of a class or struct, or an internal function, or a lambda function (D supports closures). e.g.: import std.stdio; void callit(void delegate() dg) { // call delegate with context pointer dg(); } void main() { int x; auto dg = ()=writeln(++x); // create a delegate using a lambda function callit(dg); callit(dg); callit(dg); callit(dg); } -Steve
Re: best D way to port C style array of void*
On Tue, 05 Feb 2013 23:17:59 -0500, Steven Schveighoffer schvei...@yahoo.com wrote: e.g.: import std.stdio; void callit(void delegate() dg) { // call delegate with context pointer dg(); } void main() { int x; auto dg = ()=writeln(++x); // create a delegate using a lambda function callit(dg); callit(dg); callit(dg); callit(dg); } Forgot to say, the output here would be: 1 2 3 4 -Steve
Re: best D way to port C style array of void*
Thanks for your help, much appreciated. I'm using the delegates now for the callbacks. At your suggestion I'm looking for a good way to change the design. I agree, the D type system is way superior to that of C. Starting to get into mixins too, although I'm a bit wary of them. I know they're not macros, but I once had to debug (and eventually rewrote) ~5000 lines of macros that calculate interpolated XYZ values...still recovering :) Cheers, Stewart
Re: Regarding isSorted
On 6-2-2013 1:33, bearophile wrote: Maybe this line: https://github.com/D-Programming-Language/phobos/blob/master/std/algorithm.d#L9237 for (; !ahead.empty; ahead.popFront(), ++i) Should be: for (; !ahead.empty; ahead.popFront(), r.popFront(), ++i) Thought that line looked fishy. But I don't understand half the code in Phobos so I figured it must be me...
type of if statement used for operator overloading?
I've seen operator overloading done 3 different ways. In the examples I provide they all compile and work as far as I can tell. Is there any major difference between using a static if vs a regular if, or any situation that one would be better than the other? struct Something1 { Something1 opUnary(string s)() { if (s == -) { return stuff; } } } struct Something2 { Something2 opUnary(string s)() { static if (s == -) { return stuff; } } } Also, I realize that if I wanted to overload just a single operator and that was all, I could do: struct Something3 { Something3 opUnary(string s)() if (s == -) { return stuff; } } But I am more curious about the first two. Thanks as usual guys! Jeremy
Re: type of if statement used for operator overloading?
On Wednesday, February 06, 2013 07:24:10 Jeremy DeHaan wrote: I've seen operator overloading done 3 different ways. In the examples I provide they all compile and work as far as I can tell. Is there any major difference between using a static if vs a regular if, or any situation that one would be better than the other? struct Something1 { Something1 opUnary(string s)() { if (s == -) { return stuff; } } } Don't do this. You want to be generating different functions for different overloaded operators. This just introduces extra runtime overhead. It also fails to deal with all of the possible values of s. struct Something2 { Something2 opUnary(string s)() { static if (s == -) { return stuff; } } } This is better but again fails to deal with all of the possible values of s. You'll get a nasty error message if a different value gets passed in. Also, I realize that if I wanted to overload just a single operator and that was all, I could do: struct Something3 { Something3 opUnary(string s)() if (s == -) { return stuff; } } But I am more curious about the first two. The last one is by far the best, because it protects against values for s that you don't intend to overload for. You can with the second example if you really want to and have multiple operators that you want to overload with the same function, but you still need a template constraint to protect against values that you don't intend to handle. Pretty much _every_ template that you write should have a template constraint on it. And in many cases, overloaded operators should just use string mixins. For instance, core.time.Duration does this: Duration opBinary(string op, D)(D rhs) @safe const pure nothrow if((op == + || op == -) (is(_Unqual!D == Duration) || is(_Unqual!D == TickDuration))) { static if(is(_Unqual!D == Duration)) return Duration(mixin(_hnsecs ~ op ~ rhs._hnsecs)); else if(is(_Unqual!D == TickDuration)) return Duration(mixin(_hnsecs ~ op ~ rhs.hnsecs)); } It uses static ifs to differentiate between Duration and TickDuration (since they require different code), but the code doesn't differentiate between the operators. Rather, it just mixes in the string, and it'll do the right thing in both cases. The template constraint already protects against operators that it doesn't actually overload. - Jonathan M Davis
Re: best D way to port C style array of void*
On 2013-02-06 06:49, estew wrote: Thanks for your help, much appreciated. I'm using the delegates now for the callbacks. At your suggestion I'm looking for a good way to change the design. I agree, the D type system is way superior to that of C. I would suggest you try to replace the array with something more typed, if possible. -- /Jacob Carlborg
Re: type of if statement used for operator overloading?
On Wednesday, 6 February 2013 at 06:38:11 UTC, Jonathan M Davis wrote: On Wednesday, February 06, 2013 07:24:10 Jeremy DeHaan wrote: I've seen operator overloading done 3 different ways. In the examples I provide they all compile and work as far as I can tell. Is there any major difference between using a static if vs a regular if, or any situation that one would be better than the other? struct Something1 { Something1 opUnary(string s)() { if (s == -) { return stuff; } } } Don't do this. You want to be generating different functions for different overloaded operators. This just introduces extra runtime overhead. It also fails to deal with all of the possible values of s. struct Something2 { Something2 opUnary(string s)() { static if (s == -) { return stuff; } } } This is better but again fails to deal with all of the possible values of s. You'll get a nasty error message if a different value gets passed in. Also, I realize that if I wanted to overload just a single operator and that was all, I could do: struct Something3 { Something3 opUnary(string s)() if (s == -) { return stuff; } } But I am more curious about the first two. The last one is by far the best, because it protects against values for s that you don't intend to overload for. You can with the second example if you really want to and have multiple operators that you want to overload with the same function, but you still need a template constraint to protect against values that you don't intend to handle. Pretty much _every_ template that you write should have a template constraint on it. And in many cases, overloaded operators should just use string mixins. For instance, core.time.Duration does this: Duration opBinary(string op, D)(D rhs) @safe const pure nothrow if((op == + || op == -) (is(_Unqual!D == Duration) || is(_Unqual!D == TickDuration))) { static if(is(_Unqual!D == Duration)) return Duration(mixin(_hnsecs ~ op ~ rhs._hnsecs)); else if(is(_Unqual!D == TickDuration)) return Duration(mixin(_hnsecs ~ op ~ rhs.hnsecs)); } It uses static ifs to differentiate between Duration and TickDuration (since they require different code), but the code doesn't differentiate between the operators. Rather, it just mixes in the string, and it'll do the right thing in both cases. The template constraint already protects against operators that it doesn't actually overload. - Jonathan M Davis Thanks for the info, Jonathan! I had no idea that I should constrain the kinds of operators I was overloading if I have more than two, but that makes sense and I will do this from now on. Out of curiosity, what exactly happens when we don't constrain what operators are being overloaded? Is it undefined behavior or will the program just not compile? And that is a cool use of mixins. They are still a pretty new concept to me so I haven't looked into them much. Thanks a lot for the info though! Jeremy