Re: std.container ranges

2011-10-31 Thread Tobias Pankrath
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

2011-10-31 Thread Dmitry Olshansky

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

2011-10-31 Thread Jonathan M Davis
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 ?

2011-10-31 Thread Frédéric Galusik
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 ?

2011-10-31 Thread Frédéric Galusik
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 ?

2011-10-31 Thread Steven Schveighoffer
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

2011-10-31 Thread Dmitry Olshansky

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

2011-10-31 Thread Dmitry Olshansky

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 ?!!!!)

2011-10-31 Thread Alessandro Stamatto
 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

2011-10-31 Thread Steven Schveighoffer
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?

2011-10-31 Thread bearophile
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