Re: std.container ranges
Jonathan M Davis wrote: find allows you to do that just fine, and such a remove function would simply be duplicating its functionality. But this thread serves as a proof that it is not obvious and something like containers should be obvious to use. Deleting an element with a certain value is a common task and should should not take three function calls, with functions from three different modules. You would be doing exactly the same thing in C++ except that it would be with an iterator rather than a range. You would use find to find the iterator to the element that you wanted and then you'd pass that to the list's erase function. I don't think we should refer to C++ as an benchmark for ease of use. How do you delete every occurence of v? Not just the first one? Is this equally easy with find and take? I didn't find an easy way not envolving a loop within 10 Minutes by reading the documentation. What do you think of an construct like this: foreach(item, itemRange; container) { // itemRange is a range only containing item // itemRange.length == 1 itemRange.front == item } That would be analogous to foreach over array with an index. You might think that iterating explicity may not be elegant. But it is what people want to do and it should not be any harder than necessary. -- Tobias
Re: std.container ranges
On 31.10.2011 11:16, Tobias Pankrath wrote: Jonathan M Davis wrote: find allows you to do that just fine, and such a remove function would simply be duplicating its functionality. But this thread serves as a proof that it is not obvious and something like containers should be obvious to use. Deleting an element with a certain value is a common task and should should not take three function calls, with functions from three different modules. You would be doing exactly the same thing in C++ except that it would be with an iterator rather than a range. You would use find to find the iterator to the element that you wanted and then you'd pass that to the list's erase function. I don't think we should refer to C++ as an benchmark for ease of use. How do you delete every occurence of v? Not just the first one? Is this equally easy with find and take? I didn't find an easy way not envolving a loop within 10 Minutes by reading the documentation. It is, let's use remove from std.algorithm! ... though there is no overload of remove for forward ranges ... crap, worthy of bugzilla report. Or SList could be special enough to offer a built-in remove with predicate done in O(n). However this should work( yet because of apparent bug in SList it doesn't). The bug is: Line 1294 of std.container should be: for (; !r.empty; r.popFront()) ... or it will remove the whole container. Code: import std.container, std.range; import std.functional, std.algorithm, std.stdio; void removeFromList(alias pred, T)(ref SList!T s) { static if(is(typeof(pred) == string)) alias unaryFun!pred Pred; else alias pred Pred; for(auto r=s[]; !r.empty; ) { if(Pred(r.front)) { r = s.linearRemove(take(r,1)); continue; } else r.popFront(); } } void main() { SList!int list(20, 30, 40, 50, 60); // will work with stock Phobos if the first element % 20 != 0 removeFromList!a % 20 == 0(list); writeln(list[]); } And more importantly, it still would be horribly slow O(N^2). Personally, because of that I'd prefer hand-rolled intrusive singly-linked list any time of day. What do you think of an construct like this: foreach(item, itemRange; container) { // itemRange is a range only containing item // itemRange.length == 1 itemRange.front == item } That would be analogous to foreach over array with an index. You might think that iterating explicity may not be elegant. But it is what people want to do and it should not be any harder than necessary. You still can, just use plain range interface with empty/front/popFront. for(auto r = list[]; !r.empty; r.popFront()) { ... } -- Dmitry Olshansky
Re: std.container ranges
On Monday, October 31, 2011 13:16:11 Dmitry Olshansky wrote: On 31.10.2011 11:16, Tobias Pankrath wrote: Jonathan M Davis wrote: find allows you to do that just fine, and such a remove function would simply be duplicating its functionality. But this thread serves as a proof that it is not obvious and something like containers should be obvious to use. Deleting an element with a certain value is a common task and should should not take three function calls, with functions from three different modules. You would be doing exactly the same thing in C++ except that it would be with an iterator rather than a range. You would use find to find the iterator to the element that you wanted and then you'd pass that to the list's erase function. I don't think we should refer to C++ as an benchmark for ease of use. How do you delete every occurence of v? Not just the first one? Is this equally easy with find and take? I didn't find an easy way not envolving a loop within 10 Minutes by reading the documentation. It is, let's use remove from std.algorithm! ... though there is no overload of remove for forward ranges ... crap, worthy of bugzilla report. Probably because it has to swap elements around, which requires a bidirectional range. Or SList could be special enough to offer a built-in remove with predicate done in O(n). It would be valuable in general IMHO. We should add something similar to the STL's remove_if function on linked lists. The fact that std.algorith.remove must shuffle elements around instead of actually removing them (similar to what the STL does with its free function erase) just shows how it doesn't really work all that well. It can be done _much_ more efficiently by putting remove_if (or whatever we would call it) on the container. It's also less confusing, since std.algorithm.remove (and the STL's erase function) doesn't actually _anything_. You have to pass the returned range (or iterator in C++) to the container's linearRemove function (or erase in C++) to remove the elements, which is _highly_ confusing (but since iterators and ranges don't really know about their containers beyond the elements that they reference, it's the best that can be done with a free function). For the case where you're searching for a specific element to remove though, I see no reason to add another function. That's what find is for (and given that we have lambdas, it's easy to use even in the case where you need a predicate other than ==), and if you really want to, you can iterate the range explicitly and pass the portion of the range to the container's remove function that you want to remove. The main problem with it is that we don't have proper examples, and we don't have enough documentation explaining ranges in general, so it's not immediately obvious to people how to properly use a container's remove function. - Jonathan M Davis
Re: [beginner] Why nothing is printed to stdout ?
Le Sun, 30 Oct 2011 16:44:20 -0400, Nick Sabalausky a écrit : Frédéric Galusik fr...@salixosnospam.org wrote in message news:j8j77l$pfv$1...@digitalmars.com... Hi, Can someone give me a clue on why nothing is printed to stdout ? I wish a list of files with their size. code: // import std.stdio; import std.file; void main(string[] args) { foreach (DirEntry e; dirEntries(., SpanMode.shallow)) { writeln(e.name, \t, e.size); } } // Build with (dmd2): dmd -w test.d My aplogies it you already know this, It's not my intention to be patronizing: You did run the resulting executable, right ( ./test )? And there are files in the dir its beng run from? Don't need to apologize, it's already kind to answer ;) So, Yes I run the resulting executable in my $HOME dir where there are many files. If I run it through Geany (IDE) I only got: -- (program exited with code: 1) Press return to continue If I run in my terminal, there's no output. ++ fredg
Re: [beginner] Why nothing is printed to stdout ?
Le Mon, 31 Oct 2011 00:55:58 +0400, Dmitry Olshansky a écrit : On 30.10.2011 14:00, Frédéric Galusik wrote: Hi, Can someone give me a clue on why nothing is printed to stdout ? I wish a list of files with their size. code: // import std.stdio; import std.file; void main(string[] args) { foreach (DirEntry e; dirEntries(., SpanMode.shallow)) { writeln(e.name, \t, e.size); } } // Build with (dmd2): dmd -w test.d I might be way off on this. Yet this silly stuff used to catch me all the time when switching from windows to *nixes, back and forth: sh$: compile something to 'test' sh$: test no output - WTF? Ahem, it just called that command line tool named test... sh$: ./test wow, now something happens ;) Ohhh yesss, you got it. That was so stupid, a big thanks. Regards. ++ fredg
Re: [beginner] Why nothing is printed to stdout ?
On Mon, 31 Oct 2011 06:01:05 -0400, Frédéric Galusik fr...@salixosnospam.org wrote: Le Mon, 31 Oct 2011 00:55:58 +0400, Dmitry Olshansky a écrit : On 30.10.2011 14:00, Frédéric Galusik wrote: Hi, Can someone give me a clue on why nothing is printed to stdout ? I wish a list of files with their size. code: // import std.stdio; import std.file; void main(string[] args) { foreach (DirEntry e; dirEntries(., SpanMode.shallow)) { writeln(e.name, \t, e.size); } } // Build with (dmd2): dmd -w test.d I might be way off on this. Yet this silly stuff used to catch me all the time when switching from windows to *nixes, back and forth: sh$: compile something to 'test' sh$: test no output - WTF? Ahem, it just called that command line tool named test... sh$: ./test wow, now something happens ;) Ohhh yesss, you got it. That was so stupid, a big thanks. Regards. Oh I remember doing that too :) Don't feel bad, everyone does this at least once. I hate that stupid test builtin, nobody ever uses it anymore. Note, it's not a command line tool, it's a shell builtin, which is why it overrides anything in your search path. I've since adopted the habit of calling test programs testme instead of test :) -Steve
Re: std.container ranges
On 31.10.2011 18:38, Steven Schveighoffer wrote: On Mon, 31 Oct 2011 05:16:11 -0400, Dmitry Olshansky dmitry.o...@gmail.com wrote: On 31.10.2011 11:16, Tobias Pankrath wrote: Jonathan M Davis wrote: find allows you to do that just fine, and such a remove function would simply be duplicating its functionality. But this thread serves as a proof that it is not obvious and something like containers should be obvious to use. Deleting an element with a certain value is a common task and should should not take three function calls, with functions from three different modules. You would be doing exactly the same thing in C++ except that it would be with an iterator rather than a range. You would use find to find the iterator to the element that you wanted and then you'd pass that to the list's erase function. I don't think we should refer to C++ as an benchmark for ease of use. How do you delete every occurence of v? Not just the first one? Is this equally easy with find and take? I didn't find an easy way not envolving a loop within 10 Minutes by reading the documentation. It is, let's use remove from std.algorithm! ... though there is no overload of remove for forward ranges ... crap, worthy of bugzilla report. Or SList could be special enough to offer a built-in remove with predicate done in O(n). However this should work( yet because of apparent bug in SList it doesn't). The bug is: Line 1294 of std.container should be: for (; !r.empty; r.popFront()) ... or it will remove the whole container. Code: import std.container, std.range; import std.functional, std.algorithm, std.stdio; void removeFromList(alias pred, T)(ref SList!T s) { static if(is(typeof(pred) == string)) alias unaryFun!pred Pred; else alias pred Pred; for(auto r=s[]; !r.empty; ) { if(Pred(r.front)) { r = s.linearRemove(take(r,1)); continue; } else r.popFront(); } } void main() { SList!int list(20, 30, 40, 50, 60); // will work with stock Phobos if the first element % 20 != 0 removeFromList!a % 20 == 0(list); writeln(list[]); } And more importantly, it still would be horribly slow O(N^2). Personally, because of that I'd prefer hand-rolled intrusive singly-linked list any time of day. ahem, using dcollections: foreach(ref doRemove, cell; organism.purge) doRemove = cell.x == x cell.y == y; complexity: O(n) While computer happily does O(n) work here, my brain screams in cognitive dissonance figuring out that this assignment actually does delete... meh voodoo through and through :) I'd rather organism.remove!((cell){ return cell.x == x cell.y == y; })(); or something like that. But it's not a question of form, but more of a missing stuff that should be there. :) -Steve -- Dmitry Olshansky
Re: std.container ranges
Looks like it was accidental cross-posting: On 31.10.2011 20:11, Alessandro Stamatto wrote: it still would be horribly slow O(N^2). Personally, because of that I'd prefer hand-rolled intrusive singly-linked list any time of day. Now you're scaring me... You're saying that SList in D not only is bugged, but a templated remove_if would run in O(N^2) instead of O(N) Basically I'm saying that with current SList *implementation* it will run in O(N^2), because for some reason it always do a check on each range passed to remove that it does belong to this list. (i.e. it walks from head till hits it or it's own tail) -- Dmitry Olshansky
Re: std.container ranges (n^2 ?!!!!)
it still would be horribly slow O(N^2). Personally, because of that I'd prefer hand-rolled intrusive singly-linked list any time of day. Now you're scaring me... You're saying that SList in D not only is bugged, but a templated remove_if would run in O(N^2) instead of O(N)
Re: std.container ranges
On Mon, 31 Oct 2011 12:40:37 -0400, Dmitry Olshansky dmitry.o...@gmail.com wrote: On 31.10.2011 18:38, Steven Schveighoffer wrote: On Mon, 31 Oct 2011 05:16:11 -0400, Dmitry Olshansky dmitry.o...@gmail.com wrote: On 31.10.2011 11:16, Tobias Pankrath wrote: Jonathan M Davis wrote: find allows you to do that just fine, and such a remove function would simply be duplicating its functionality. But this thread serves as a proof that it is not obvious and something like containers should be obvious to use. Deleting an element with a certain value is a common task and should should not take three function calls, with functions from three different modules. You would be doing exactly the same thing in C++ except that it would be with an iterator rather than a range. You would use find to find the iterator to the element that you wanted and then you'd pass that to the list's erase function. I don't think we should refer to C++ as an benchmark for ease of use. How do you delete every occurence of v? Not just the first one? Is this equally easy with find and take? I didn't find an easy way not envolving a loop within 10 Minutes by reading the documentation. It is, let's use remove from std.algorithm! ... though there is no overload of remove for forward ranges ... crap, worthy of bugzilla report. Or SList could be special enough to offer a built-in remove with predicate done in O(n). However this should work( yet because of apparent bug in SList it doesn't). The bug is: Line 1294 of std.container should be: for (; !r.empty; r.popFront()) ... or it will remove the whole container. Code: import std.container, std.range; import std.functional, std.algorithm, std.stdio; void removeFromList(alias pred, T)(ref SList!T s) { static if(is(typeof(pred) == string)) alias unaryFun!pred Pred; else alias pred Pred; for(auto r=s[]; !r.empty; ) { if(Pred(r.front)) { r = s.linearRemove(take(r,1)); continue; } else r.popFront(); } } void main() { SList!int list(20, 30, 40, 50, 60); // will work with stock Phobos if the first element % 20 != 0 removeFromList!a % 20 == 0(list); writeln(list[]); } And more importantly, it still would be horribly slow O(N^2). Personally, because of that I'd prefer hand-rolled intrusive singly-linked list any time of day. ahem, using dcollections: foreach(ref doRemove, cell; organism.purge) doRemove = cell.x == x cell.y == y; complexity: O(n) While computer happily does O(n) work here, my brain screams in cognitive dissonance figuring out that this assignment actually does delete... meh voodoo through and through :) I'd rather organism.remove!((cell){ return cell.x == x cell.y == y; })(); or something like that. But it's not a question of form, but more of a missing stuff that should be there. That could also be added (and I agree it's a good idea). Alas, interface templates still don't work, so it'd have to be defined as a convention. Note that this isn't really the intended usage for purge (though it works quite nicely as an afterthought). Typically, when I use purge, I'm iterating through all the elements, processing them somehow, and then deciding to remove them or not based on the processing. For instance, a main thread processing results from sub-threads, and removing ones that are finished. Think of it as an implementation of Java's Iterator.remove: http://download.oracle.com/javase/7/docs/api/java/util/Iterator.html#remove() -Steve
Re: Can't free memory on exiting?
Andrej Mitrovic: Otherwise if you want to use the GC there's no point in calling GC.free in the destructor since the GC will do that automatically. And if the OP wants some determinism in the dellocation of the memory allocated with malloc, the OP has to use a struct (scope classes used to give the same determinism, but they are deprecated). Bye, bearophile