On 11/2/11 8:48 AM, Steven Schveighoffer wrote:
On Tue, 01 Nov 2011 16:53:26 -0400, Max Wolter <awishform...@gmail.com>
wrote:
On 10/30/2011 9:28 PM, Jonathan M Davis wrote:
On Sunday, October 30, 2011 20:53:02 Max Wolter wrote:
Hello there.
Thank you very much for the explanation.
However, while I really liked the concept of ranges in Andrei's book
and
a lot of it seems intuitive and faster than using iterators, I can't
shake the feeling that in this case, it's just unnecessarily
convoluted.
Maybe it's just the fact that the container library is still very
basic,
but I don't think I should go through such a complicated procedure to
remove an known element from a list. It's just not a "very simple" or
intuitive solution, which is something I came to love D for thus far.
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.
It is only more complicated in D in that you get a range which
_starts_ with
the element that you want (essentially, you get the iterator to that
element
plus the end iterator for the list), so if you want to remove only
the first
element, you take it from the front of the range. Other than that,
it's the
same as in C++. You can't remove an element from a list in C++ by
giving that
element to the list anymore than you can in D. In both cases, you
need an
iterator or a range.
So, in comparison to C++, there's no significant difference. Now,
Java does have
a remove function which will take an element and remove the first
occurence of
that element from a list, and we could theoretically add one, but
why? It
would just be duplicating the functionality that find already gives.
Java
doesn't use iterators the way the C++ does, and it doesn't have
ranges, so it
_can't_ have a find function the way that C++ and D do, but D can.
And in some
cases, find can do it more efficiently than your loop could have.
I grant you that if you're not used to using find like this in C++
(and far,
far too many C++ programmers use loops instead of find - in part
because pre-
C++11, there were no lambdas and any time you need a custom comparison
function, it's a pain to get one), then it's not immediately
intuitive, but
it's far more flexible and powerful than removing elements by giving the
element to a remove function on the list. And if you really want to
use a
loop, then you still can. You just can't use foreach.
for(auto r = organism[]; !r.empty; r.popFront())
{
if(r.front.x == x&& r.front.y == y)
{
organism.stableLinearRemove(take(r, 1));
break;
}
}
but that's a lot more verbose than simply using find, and as I said,
in at
least some cases, find can be more efficient than simply looping,
since it's
optimized for finding elements.
- Jonathan M Davis
Hello again.
I've read all further replies in this thread, but it seems to me this
is the most appropriate place to respond.
Simply put, all of those options are too verbose. If what you want to
do is simple, the syntax should also be simple, this is what I love
about D. As a side-note, I don't come from Java, but I still expect a
container to be able to remove an element by passing it to a method.
The verbosity and the details of this operation should be hidden in
the implementation of the method and I shouldn't need to know about
the details. Otherwise, I could just as well implement my own container.
The basic response to this is, when dealing with containers generically
(that is, you know you have a container, but you don't know what type),
the "remove this element" operation is not necessarily a good primitive
to have.
Simply because from the myriad of containers, only some can implement
this operation efficiently. Java embeds this operation in the interface,
which means any interface you have to a container could potentially use
O(n) time to remove that element. Such an innocuous piece of syntax
*should* have a cost if it's not efficient IMO.
BTW, the original question doesn't provide enough information to say
"remove this element." Even in Java, if you aren't using the default
comparison, you must use a comparator method to determine which one to
remove. If cell.x == x && cell.y == y *is* the comparison operator for
the type, then the syntax gets much simpler, because you don't need to
pass a specialized comparison function.
In dcollections, removing a specific element (using the default
comparison operator for that element) on a *fast lookup* container is as
simple as:
container.remove(container.find(x));
Which removes the element x if it's found. However, this is not defined
for containers which use O(n) time to search (such as linked list), you
must use std.algorithm.find for that:
container.remove(find(container[], x).begin);
Should work, and takes O(n) time.
-Steve
I don't really understand what's wrong with inefficient methods. You can
have inefficient methods that are convenient, like removing an element
by the default comparison, or giving it a delegate to match the
element(s) to remove.
You profile your application. Is that method the bottle-neck? If so, you
change it to a more efficient one. If not, you are happy you had that
method there, performing in an inefficient way, but which doesn't matter
that much compared to, say, opening an SQL connection.
Programmers want to program, fast. They have schedules, they need to
deliver. They don't need to always find the best solution. They can find
a compromise between "working" and "fast", move on, and later profile
and worry about what matters most.
Programmers don't want to fight with the language or think "Oh, so to
remove an element I need to use this operation and combine it with that
one and with that other one"...