Re: implicit conversion to alias this
On Thursday, 28 June 2012 at 04:43:07 UTC, BLM768 wrote: On Monday, 25 June 2012 at 20:06:21 UTC, Tobias Pankrath wrote: - struct A { bool a; alias a this; } struct B { int b; alias b this; } A a = false; // works B b = 12; // works struct C { A aa; B ab; } C c = { false, 12 }; // does not work, because the implicit conversion does not happen. - What is the reason to allow the first two assignments? Isn't it just another implicit conversion that shouldn't be allowed? The compiler isn't "smart" enough to realize that you're trying to use an implicit conversion. It's only told to expect the conversion in certain situations, such as assignment, and getting it to work for rarer cases would involve patching it with more special-case code. The initializer is also expecting struct _values_; I don't think that you could call a function that wants an A and give it a bool, either. Making a struct value from an expression and initializing a struct in a definition are subtly different and follow different codepaths in the compiler. I'm fine that the assignment to C is verboten. I'd disallow the first assignments to and would like to know, why they are kept.
Re: implicit conversion to alias this
On Monday, 25 June 2012 at 20:06:21 UTC, Tobias Pankrath wrote: - struct A { bool a; alias a this; } struct B { int b; alias b this; } A a = false; // works B b = 12; // works struct C { A aa; B ab; } C c = { false, 12 }; // does not work, because the implicit conversion does not happen. - What is the reason to allow the first two assignments? Isn't it just another implicit conversion that shouldn't be allowed? The compiler isn't "smart" enough to realize that you're trying to use an implicit conversion. It's only told to expect the conversion in certain situations, such as assignment, and getting it to work for rarer cases would involve patching it with more special-case code. The initializer is also expecting struct _values_; I don't think that you could call a function that wants an A and give it a bool, either. Making a struct value from an expression and initializing a struct in a definition are subtly different and follow different codepaths in the compiler.
Re: Stack overflow / recursive expansion with alias this
On Tuesday, 24 April 2012 at 20:09:32 UTC, Namespace wrote: On Tuesday, 24 April 2012 at 19:34:26 UTC, Timon Gehr wrote: On 04/24/2012 07:09 PM, Namespace wrote: ... And therefore i get the same error, as if i wrote "return NotNull!(Foo)(this);" instead of "return assumeNotNull(this);", in the "_convert" method of NotNull. The Output is "Stack overflow". I think that comes from recursive calls which fills the stack? Is that a bug? Yes. I found nothing like that. Is the bug reported? I remember reporting a similar issue, but that one seems to have been fixed. Feel free to create a new ticket. That's what I do now. Thanks a lot for your help. Today I posted a pull to detect recursive alias this dependency. https://github.com/D-Programming-Language/dmd/pull/1028 Bye. Kenji Hara
Re: Removing from SList (std.container)...
On Thursday, June 28, 2012 00:23:03 Minas Mina wrote: > Doesn't Andrei plan to do something about this module? He came up with the basic design, and he's working on the custom allocator design. Once that's been sorted out, std.container will be made to use it, and more containers will be added to it. We're trying to avoid having to implement the containers twice (as would happen to at least some extent if we added them all and then added the custom allocators later), which is why there aren't more of them yet. But Andrei has been very busy, so progress has been slow, and I don't know where he stands with it right now. - Jonathan M Davis
Re: Concurrency in D
You all helped, thank you :) I will read the concurrency part tomorrow!
Re: Concurrency in D
On 06/27/2012 04:05 PM, Adam Burton wrote: >> For example I would like to >> have a thread calculate the sum of the first half of an array >> while another thread would calculate the other half, and I could >> add the two results at the end. > For this task there is another concurrency module called std.parallelism > that is designed for this type of thing (afaik). > http://dlang.org/phobos/std_parallelism.html TDPL predates std.parallelism, so it's not in the book. Although the module's documentation is straightforward, I have the following page which may be more accessible for some: http://ddili.org/ders/d.en/parallelism.html Clicking [Next] on that pages goes to Message Passing Concurrency: http://ddili.org/ders/d.en/concurrency.html Ali P.S. Both of those pages are incomplete in some ways, which I will address soon.
Re: Concurrency in D
On Wednesday, 27 June 2012 at 22:34:51 UTC, Minas Mina wrote: I have been "playing" latetly with std.concurrency and core.thread. I like both, but they are entirely different approaches to concurrency. Aren't they great? ;) std.concurrency: Uses message passing. Does not allow passing of mutable types. core.thread: Essentially the same as the approach taken by Java. 1) Is one favoured over the other? I guess std.concurrency would be, because it uses messages (and I recently read somewhere that immutability + message passing = good thing). Personally I favor std.concurrency, in many cases I find it faster. Well, my problem about is, how can send mutable data to another thread? _Can_ I do it? If not, how am I supposed to share data between them? Not everything can be immutable right? Mutable value types can be sent easily, because they are copied. You share data with shared(T) types, e.g. shared(Object) or shared(int[]). However, I try to avoid shared data by keeping it in single threads, and having other threads access parts with message passing. One paradigm is to isolate data into "thread objects," threads which have non-shared data on the stack, and have other threads send GetData messages and get ReturnedData messages. For example I would like to have a thread calculate the sum of the first half of an array while another thread would calculate the other half, and I could add the two results at the end. Check out this: http://dpaste.dzfl.pl/0f7ccb79 Note that for algorithms like this, you should check out std.parallelism, it's more high-level than std.concurrency. 2) What about core.thread? To do proper sync between threads in core.thread, semaphore, mutexes and stuff like that are needed. Are those "good practice" in D? Part of D's philosophy is "you can get low-level and dirty if you want, but the easy/safe way should also be the fast way." core.thread is there for you, but std.concurrency is easier. Note that std.concurrency is written on top of core.thread. I definitely prefer std.concurrency, but I don't write CPU-intensive stuff anyway, so I'm no expert. 3) I have also read a bit about syncronized classes and shared classes/structs, altough I didn't understand it too much (well I didn't try too much to be honest). Objects of a synchronized class automatically lock/unlock every method call. You don't share stack structs, though maybe shared(StructType)*. For all those appoaches, which is the preffered? For all those appoaches, which is the preffered for game programming? Thank you. Hope I've helped. NMS
Re: Concurrency in D
On Thu, 28 Jun 2012 00:34:50 +0200, Minas Mina wrote: > I have been "playing" latetly with std.concurrency and core.thread. I > like both, but they are entirely different approaches to concurrency. > > std.concurrency: Uses message passing. Does not allow passing of mutable > types. > core.thread: Essentially the same as the approach taken by Java. > > 1) Is one favoured over the other? I guess std.concurrency would be, > because it uses messages (and I recently read somewhere that > immutability + message passing = good thing). Well, my problem about is, > how can send mutable data to another thread? _Can_ I do it? If not, how > am I supposed to share data between them? Not everything can be > immutable right? For example I would like to have a thread calculate the > sum of the first half of an array while another thread would calculate > the other half, and I could add the two results at the end. > > 2) What about core.thread? To do proper sync between threads in > core.thread, semaphore, mutexes and stuff like that are needed. Are > those "good practice" in D? > > 3) I have also read a bit about syncronized classes and shared > classes/structs, altough I didn't understand it too much (well I didn't > try too much to be honest). > > For all those appoaches, which is the preffered? > For all those appoaches, which is the preffered for game programming? > > Thank you. Concurrency and parallelism are two related, but different concepts. Concurrency is when you have different computations conducted simultaneously. An example is a modern game engine: you may have a rendering thread, a physics simulation, and a networking stack all operating at the same time on different cores. Concurrency allows (and generally assumes) communication between these parts as they need to share information. Message-passing is, as far as I know, pretty much the only truly correct way of doing this. Parallelism is, by contrast, the decomposing of a computation into smaller chunks which do not depend on each other. A trivial example is incrementing all integers in an array by one--the result of the increment computation only relies on the integer being worked on, so the computations may be performed in parallel and the results collected. The std.concurrency and std.parallelism thus exist to solve two different problems and are more of an apples-oranges situation. Justin
Re: Concurrency in D
Minas Mina wrote: > I have been "playing" latetly with std.concurrency and > core.thread. I like both, but they are entirely different > approaches to concurrency. > > std.concurrency: Uses message passing. Does not allow passing of > mutable types. > core.thread: Essentially the same as the approach taken by Java. > > 1) Is one favoured over the other? I guess std.concurrency would > be, because it uses messages (and I recently read somewhere that > immutability + message passing = good thing). I've not really got around to doing any concurrent programming in anger with D yet but from what I've read message passing is the preferred method. Fortunately when it comes to answering your question the concurrency chapter for The D Programming Language book (TDPL) was made freely available as a preview http://www.informit.com/articles/article.aspx?p=1609144. Hopefully that contains your answers :). > Well, my problem > about is, how can send mutable data to another thread? _Can_ I do > it? If not, how am I supposed to share data between them? Not > everything can be immutable right? >From what I gather this is where the shared keyword typically comes into play which should be detailed in the url above. > For example I would like to > have a thread calculate the sum of the first half of an array > while another thread would calculate the other half, and I could > add the two results at the end. For this task there is another concurrency module called std.parallelism that is designed for this type of thing (afaik). http://dlang.org/phobos/std_parallelism.html > > 2) What about core.thread? To do proper sync between threads in > core.thread, semaphore, mutexes and stuff like that are needed. > Are those "good practice" in D? > > 3) I have also read a bit about syncronized classes and shared > classes/structs, altough I didn't understand it too much (well I > didn't try too much to be honest). > > For all those appoaches, which is the preffered? My observation is std.concurrency is being pushed as the preferred default method. > For all those appoaches, which is the preffered for game > programming? > > Thank you.
Concurrency in D
I have been "playing" latetly with std.concurrency and core.thread. I like both, but they are entirely different approaches to concurrency. std.concurrency: Uses message passing. Does not allow passing of mutable types. core.thread: Essentially the same as the approach taken by Java. 1) Is one favoured over the other? I guess std.concurrency would be, because it uses messages (and I recently read somewhere that immutability + message passing = good thing). Well, my problem about is, how can send mutable data to another thread? _Can_ I do it? If not, how am I supposed to share data between them? Not everything can be immutable right? For example I would like to have a thread calculate the sum of the first half of an array while another thread would calculate the other half, and I could add the two results at the end. 2) What about core.thread? To do proper sync between threads in core.thread, semaphore, mutexes and stuff like that are needed. Are those "good practice" in D? 3) I have also read a bit about syncronized classes and shared classes/structs, altough I didn't understand it too much (well I didn't try too much to be honest). For all those appoaches, which is the preffered? For all those appoaches, which is the preffered for game programming? Thank you.
Re: Removing from SList (std.container)...
Doesn't Andrei plan to do something about this module?
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 21:38:28 UTC, Jonathan M Davis wrote: On Wednesday, June 27, 2012 22:29:01 Roman D. Boiko wrote: On Wednesday, 27 June 2012 at 20:14:53 UTC, Steven Schveighoffer wrote: > Removal of that element is perfectly possible, you just need > to > maintain a reference to its predecessor. Which SList's range > does not keep track of. It all depends on tradeoffs of what > you want for performance, vs. features. It's why I contend > that generic singly linked list is difficult to create. Can't > please everyone. Yes, I agree. > And iterators are not necessary, ranges are quite possible. In this respect it is not only a performance vs. features tradeoff, semantics is (usually) different. Of course, we might use a range for what is semantically an iterator. But it feels unnatural for me. E.g., to point to an element in the middle of some range we would need to create another range and pass it to a function along with the original range. I would hesitate to call them ranges unless that is explicitly a goal for some particular application. If that was the case, it would require an explicit explanation. (IMO) If you want a single element, then use take, takeExactly, or takeOne. For instance, that's what you do when you want to use remove in std.container (though apparently takeOne was missed as pointed out earlier in this thread, which needs to be remedied). It is true that dealing with ranges in this sort of situation is a bit more problematic than it is with iterators, but the take* functions take care of it as long as the container properly takes them into account (which std.container's containers are supposed to do). And if all you care about is having a range with one element and not whether the range is passable to a function on it's associated container, then the take* functions work just fine regardless of whether the container properly takes them into account. It's only an issue with the container, because the container needs its original range type rather than some arbitrary range which may have nothing to do with that container (the same happens with iterators - you just don't tend to wrap them in other types in the same way that happens with ranges). - Jonathan M Davis It depends entirely on intended semantics and use cases. There is a difference between a range, an iterator, and a link (pointer) to some container node. I meant a link when I used the term "iterator". To illustrate, imagine a tree container. A link could point to some node, which could be used conceptually as a container. A range would define a subset of either element values or links for some traversal. So a range semantically implies an ordering, and is quite different from a link. An iterator seems to be closer to a range in this respect, that's why I admitted that I used the term incorrectly.
Re: Removing from SList (std.container)...
On Wednesday, June 27, 2012 22:29:01 Roman D. Boiko wrote: > On Wednesday, 27 June 2012 at 20:14:53 UTC, Steven Schveighoffer > > wrote: > > Removal of that element is perfectly possible, you just need to > > maintain a reference to its predecessor. Which SList's range > > does not keep track of. It all depends on tradeoffs of what > > you want for performance, vs. features. It's why I contend > > that generic singly linked list is difficult to create. Can't > > please everyone. > > Yes, I agree. > > > And iterators are not necessary, ranges are quite possible. > > In this respect it is not only a performance vs. features > tradeoff, semantics is (usually) different. Of course, we might > use a range for what is semantically an iterator. But it feels > unnatural for me. > > E.g., to point to an element in the middle of some range we would > need to create another range and pass it to a function along with > the original range. I would hesitate to call them ranges unless > that is explicitly a goal for some particular application. If > that was the case, it would require an explicit explanation. (IMO) If you want a single element, then use take, takeExactly, or takeOne. For instance, that's what you do when you want to use remove in std.container (though apparently takeOne was missed as pointed out earlier in this thread, which needs to be remedied). It is true that dealing with ranges in this sort of situation is a bit more problematic than it is with iterators, but the take* functions take care of it as long as the container properly takes them into account (which std.container's containers are supposed to do). And if all you care about is having a range with one element and not whether the range is passable to a function on it's associated container, then the take* functions work just fine regardless of whether the container properly takes them into account. It's only an issue with the container, because the container needs its original range type rather than some arbitrary range which may have nothing to do with that container (the same happens with iterators - you just don't tend to wrap them in other types in the same way that happens with ranges). - Jonathan M Davis
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 21:22:31 UTC, Tobias Pankrath wrote: E.g., to point to an element in the middle of some range we would need to create another range and pass it to a function along with the original range. I would hesitate to call them ranges unless that is explicitly a goal for some particular application. If that was the case, it would require an explicit explanation. (IMO) Why pass the original range? I mean the range on which to perform an operation. It could be passed via this parameter of member function or explicitly. It could be not needed for some operations (trivial, like copy or compare).
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 20:29:02 UTC, Roman D. Boiko wrote: On Wednesday, 27 June 2012 at 20:14:53 UTC, Steven Schveighoffer wrote: Removal of that element is perfectly possible, you just need to maintain a reference to its predecessor. Which SList's range does not keep track of. It all depends on tradeoffs of what you want for performance, vs. features. It's why I contend that generic singly linked list is difficult to create. Can't please everyone. Yes, I agree. And iterators are not necessary, ranges are quite possible. In this respect it is not only a performance vs. features tradeoff, semantics is (usually) different. Of course, we might use a range for what is semantically an iterator. But it feels unnatural for me. E.g., to point to an element in the middle of some range we would need to create another range and pass it to a function along with the original range. I would hesitate to call them ranges unless that is explicitly a goal for some particular application. If that was the case, it would require an explicit explanation. (IMO) Why pass the original range?
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 20:14:53 UTC, Steven Schveighoffer wrote: Removal of that element is perfectly possible, you just need to maintain a reference to its predecessor. Which SList's range does not keep track of. It all depends on tradeoffs of what you want for performance, vs. features. It's why I contend that generic singly linked list is difficult to create. Can't please everyone. Yes, I agree. And iterators are not necessary, ranges are quite possible. In this respect it is not only a performance vs. features tradeoff, semantics is (usually) different. Of course, we might use a range for what is semantically an iterator. But it feels unnatural for me. E.g., to point to an element in the middle of some range we would need to create another range and pass it to a function along with the original range. I would hesitate to call them ranges unless that is explicitly a goal for some particular application. If that was the case, it would require an explicit explanation. (IMO)
Re: Removing from SList (std.container)...
On Wed, 27 Jun 2012 15:57:42 -0400, Roman D. Boiko wrote: On Wednesday, 27 June 2012 at 19:55:02 UTC, Roman D. Boiko wrote: Look up SList docs, even with a reference to a *specific element*, you cannot do O(1) removal. Ha-ha, didn't know SList doesn't support that. I somehow confused removal after a referenced element (which should be easy to implement, but not very useful) with removal of that element (which is not possible in 0(1) in a singly-linked list. Removal of that element is perfectly possible, you just need to maintain a reference to its predecessor. Which SList's range does not keep track of. It all depends on tradeoffs of what you want for performance, vs. features. It's why I contend that generic singly linked list is difficult to create. Can't please everyone. And iterators are not necessary, ranges are quite possible. -Steve
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 20:00:18 UTC, Roman D. Boiko wrote: Nice. But forces to use iterators everywhere. (I'm not against iterators, they are almost necessary in certain use cases, like this one.)
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 19:06:46 UTC, Timon Gehr wrote: On 06/27/2012 08:46 PM, Roman D. Boiko wrote: On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer wrote: The thing that makes SList useless is the O(n) removal. Nobody will ever use SList when they can write a replacement that has O(1) removal in 10 minutes. Do you mean something like indexed/sorted dictionary? It doesn't seem to be that easy to implement. Or some other data structure with O(1) removal? O(1) removal works quite ok for a singly linked list. eg: 1. - Add a sentinel node to the start of your list. - Represent an iterator into the list as a pointer to the predecessor of the respective node. - Removal: trivial. rebind the 'next' reference of the pointed-to node. 2. - Represent the empty list as a sentinel node with null 'next' field. - For removal of a node you own a pointer to: -- case 1: the successor is an empty list: - destroy the value, set the 'next' reference to null. -- case 2: else: - move the successor's value into the node that holds the value to be removed, bind the 'next' reference to the successor of the successor. Nice. But forces to use iterators everywhere.
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 19:55:02 UTC, Roman D. Boiko wrote: Look up SList docs, even with a reference to a *specific element*, you cannot do O(1) removal. Ha-ha, didn't know SList doesn't support that. I somehow confused removal after a referenced element (which should be easy to implement, but not very useful) with removal of that element (which is not possible in 0(1) in a singly-linked list.
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 19:10:24 UTC, Steven Schveighoffer wrote: On Wed, 27 Jun 2012 14:46:36 -0400, Roman D. Boiko wrote: On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer wrote: The thing that makes SList useless is the O(n) removal. Nobody will ever use SList when they can write a replacement that has O(1) removal in 10 minutes. Do you mean something like indexed/sorted dictionary? It doesn't seem to be that easy to implement. Or some other data structure with O(1) removal? struct Link { int val; Link *next; removeNext() {assert(next); next = next.next;} } O(1) removal, easy as that. I thought you meant removal by index or value, not element reference. Look up SList docs, even with a reference to a *specific element*, you cannot do O(1) removal. Ha-ha, didn't know SList doesn't support that.
Re: Removing from SList (std.container)...
On Wed, 27 Jun 2012 14:46:36 -0400, Roman D. Boiko wrote: On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer wrote: The thing that makes SList useless is the O(n) removal. Nobody will ever use SList when they can write a replacement that has O(1) removal in 10 minutes. Do you mean something like indexed/sorted dictionary? It doesn't seem to be that easy to implement. Or some other data structure with O(1) removal? struct Link { int val; Link *next; removeNext() {assert(next); next = next.next;} } O(1) removal, easy as that. Look up SList docs, even with a reference to a *specific element*, you cannot do O(1) removal. Only recently did it add O(1) insertion, but only after a specific element. Good luck implementing a way to do insert *before* that element in O(1), it will be possible, but really obtuse. -Steve
Re: Removing from SList (std.container)...
On 06/27/2012 08:46 PM, Roman D. Boiko wrote: On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer wrote: The thing that makes SList useless is the O(n) removal. Nobody will ever use SList when they can write a replacement that has O(1) removal in 10 minutes. Do you mean something like indexed/sorted dictionary? It doesn't seem to be that easy to implement. Or some other data structure with O(1) removal? O(1) removal works quite ok for a singly linked list. eg: 1. - Add a sentinel node to the start of your list. - Represent an iterator into the list as a pointer to the predecessor of the respective node. - Removal: trivial. rebind the 'next' reference of the pointed-to node. 2. - Represent the empty list as a sentinel node with null 'next' field. - For removal of a node you own a pointer to: -- case 1: the successor is an empty list: - destroy the value, set the 'next' reference to null. -- case 2: else: - move the successor's value into the node that holds the value to be removed, bind the 'next' reference to the successor of the successor.
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 18:26:46 UTC, Steven Schveighoffer wrote: The thing that makes SList useless is the O(n) removal. Nobody will ever use SList when they can write a replacement that has O(1) removal in 10 minutes. Do you mean something like indexed/sorted dictionary? It doesn't seem to be that easy to implement. Or some other data structure with O(1) removal?
Re: Removing from SList (std.container)...
On Wed, 27 Jun 2012 13:44:34 -0400, Jonathan M Davis wrote: On Wednesday, June 27, 2012 08:25:04 Steven Schveighoffer wrote: On Wed, 27 Jun 2012 05:37:00 -0400, Minas Mina wrote: > How can I do that? > > Why not list.remove(x); like in STL? SList is quite unusable. If you are looking for STL-like containers, there is dcollections which has a doubly-linked list, and supports syntax like you want. http://www.dsource.org/projects/dcollections There concept of SList is unusable IMHO. The singly-linked list is one of the most useless data structures ever invented. It does have some use cases, but almost always what you really want is doubly-linked list. The thing that makes SList useless is the O(n) removal. Nobody will ever use SList when they can write a replacement that has O(1) removal in 10 minutes. The concept of singly-linked lists is most certainly not useless. They are perfect for FIFO queues, or LIFO stacks, and they consume 1/3 less space than a doubly-linked list (at least for an int/size_t) My somewhat loose belief is that making a generic singly-linked list is a waste of time -- it's too difficult to implement in a way that is optimized for the intended use. As for std.container, the basics of std.container are good, but the documentation isn't good enough for some basic stuff, and some of it needs to be ironed out a bit. For instance, the basic idea of how remove works is fine given how ranges work (though it's arguably one of those few places where ranges are worse than iterators - hence why dcollections has cursors), and it's exactly what you want in the general case, but it's arguably overly complicated for a lot of basic use cases. Adding stuff like removeFirst which removed the first value which matched would greatly simplify a number of basic use cases. I haven't used std.container all that much, but I find the terminology very obtuse and verbose. I can't imagine every using for example upperBound without having to look up what it does. I understand the point, but it needs shortcuts. Like how you can type writeln("x") instead of stdout.writeln("x"). I think that's a small difference that is a huge win. But regardless, any API improvements pale in comparison to the O(n) removal problem for SList. I've been meaning to figure out a small set of basic functions like that which would improve the API's usability for many common cases and propose them, but there hasn't been much point in trying to do anything with it, since that sort of thing needs to get passed Andrei (who is likely to say that the current solution with find and take is just fine, since it's nicely generic and covers all use cases), but he's been busy. It doesn't hurt to propose... Personally, I don't see myself ever using std.container when I prefer the API of dcollections. But that obviously isn't going to be the popular choice, since it's not in phobos. -Steve
Re: Removing from SList (std.container)...
On Wednesday, June 27, 2012 08:25:04 Steven Schveighoffer wrote: > On Wed, 27 Jun 2012 05:37:00 -0400, Minas Mina > > wrote: > > How can I do that? > > > > Why not list.remove(x); like in STL? > > SList is quite unusable. > > If you are looking for STL-like containers, there is dcollections which > has a doubly-linked list, and supports syntax like you want. > > http://www.dsource.org/projects/dcollections There concept of SList is unusable IMHO. The singly-linked list is one of the most useless data structures ever invented. It does have some use cases, but almost always what you really want is doubly-linked list. As for std.container, the basics of std.container are good, but the documentation isn't good enough for some basic stuff, and some of it needs to be ironed out a bit. For instance, the basic idea of how remove works is fine given how ranges work (though it's arguably one of those few places where ranges are worse than iterators - hence why dcollections has cursors), and it's exactly what you want in the general case, but it's arguably overly complicated for a lot of basic use cases. Adding stuff like removeFirst which removed the first value which matched would greatly simplify a number of basic use cases. I've been meaning to figure out a small set of basic functions like that which would improve the API's usability for many common cases and propose them, but there hasn't been much point in trying to do anything with it, since that sort of thing needs to get passed Andrei (who is likely to say that the current solution with find and take is just fine, since it's nicely generic and covers all use cases), but he's been busy. - Jonathan M Davis
Re: Removing from SList (std.container)...
On Wed, 27 Jun 2012 05:37:00 -0400, Minas Mina wrote: How can I do that? Why not list.remove(x); like in STL? SList is quite unusable. If you are looking for STL-like containers, there is dcollections which has a doubly-linked list, and supports syntax like you want. http://www.dsource.org/projects/dcollections -Steve
Re: Removing from SList (std.container)...
Thank you for your reply. Yes, std.container really sucks. Anyway, I made my program using C++ and STL
Re: Bug in Auto Functions and Template? Or Am I Just Crazy...
On 06/27/2012 01:24 PM, Timon Gehr wrote: On 06/27/2012 11:07 AM, Michael wrote: Hello all, I came across some weird behaviors yesterday and I can't figure out what it's about. (1) auto factorial(int n) { if (n < 2) return 1; return n * factorial(n-1); } The compiler complained about "forward declaration of factorial". If I change the return type to int, the problem goes away. I can understand that with the recursion, it might be impossible for the compiler to deduce the type of factorial and so it compile errors, but I don't see anything about that on the Language Reference. Is this the intended behavior? Apparently the compiler attempts to type combine the types of the return statements. This does not match the language documentation. I think it should just use the type of the first return statement. ... http://d.puremagic.com/issues/show_bug.cgi?id=8307
Re: Bug in Auto Functions and Template? Or Am I Just Crazy...
On 06/27/2012 11:07 AM, Michael wrote: Hello all, I came across some weird behaviors yesterday and I can't figure out what it's about. (1) auto factorial(int n) { if (n < 2) return 1; return n * factorial(n-1); } The compiler complained about "forward declaration of factorial". If I change the return type to int, the problem goes away. I can understand that with the recursion, it might be impossible for the compiler to deduce the type of factorial and so it compile errors, but I don't see anything about that on the Language Reference. Is this the intended behavior? Apparently the compiler attempts to type combine the types of the return statements. This does not match the language documentation. I think it should just use the type of the first return statement. (2) auto stuff(T)(T[] arr) { auto inner(T[] s) { s[0] = 0; } arr.inner(); } This time the compiler complained about 'inner' not being defined. This time I have no idea what is wrong. Thanks for your help! Michael This is expected behaviour. UFCS only works with module scope functions.
Re: Removing from SList (std.container)...
Can you show me an example or removing a number? I think that is a prime example of why std.container sucks both in documentation and implemantation. We really need to improve here, sadly development seems to be bottlenecked by Andrei working on on allocator proposal. And Andrei is busy at the moment. Here is the solution. You actually need 4 different modules from phobos to do this and it is absolutely not obvious how to do it. import std.algorithm; import std.range; import std.container; import std.array; void main(string[] args) { SList!int list = [1,2,3,4,5]; // our list writeln(list.array()); // need to create an array to print nicely auto pos = find(list[], 4); // we need a range, so we search for the number auto pos2 = take(pos, 1); // but find returns a range over the rest, so take one list.linearRemove(pos2); // remove it writeln(list.array()); // print it } I needed to look it up myself and didn't find a solution on first try. My first error: You can't just do find(list, 4), because an SList is not a range by itself. So you need opSlice (list[]) to get a range over list. Then I knew already that find gives me not what I want. I somehow need to restrict the range pos to the first element. But how to do it? I wouldn't expect a newcomer to come up with a solution on its own, because pos[0..1] will not work on a forward range. Luckily I knew std.range.takeOne. But hold! takeOne(pos) does not work, you need take(pos, 1). That sucks. None of the above is stated explicitly in the documentation. I knew that the container generally need a range that was extracted from them. How should I know that in this special case a range from std.range will work, too? And not all ranges work, only the one from take.
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 09:52:14 UTC, Tobias Pankrath wrote: On Wednesday, 27 June 2012 at 09:37:01 UTC, Minas Mina wrote: How can I do that? Why not list.remove(x); like in STL? std.container encodes the complexity of operations in the method names. There is no way to remove a range in constant time in SList, so you only get linearRemove. And you always need a range to remove something. Can you show me an example or removing a number?
Re: Removing from SList (std.container)...
On Wednesday, 27 June 2012 at 09:37:01 UTC, Minas Mina wrote: How can I do that? Why not list.remove(x); like in STL? std.container encodes the complexity of operations in the method names. There is no way to remove a range in constant time in SList, so you only get linearRemove. And you always need a range to remove something.
Removing from SList (std.container)...
How can I do that? Why not list.remove(x); like in STL?
Re: Bug in Auto Functions and Template? Or Am I Just Crazy...
On Wednesday, 27 June 2012 at 09:07:57 UTC, Michael wrote: Hello all, I came across some weird behaviors yesterday and I can't figure out what it's about. (1) auto factorial(int n) { if (n < 2) return 1; return n * factorial(n-1); } The compiler complained about "forward declaration of factorial". If I change the return type to int, the problem goes away. I can understand that with the recursion, it might be impossible for the compiler to deduce the type of factorial and so it compile errors, but I don't see anything about that on the Language Reference. Is this the intended behavior? (2) auto stuff(T)(T[] arr) { auto inner(T[] s) { s[0] = 0; } arr.inner(); } This time the compiler complained about 'inner' not being defined. This time I have no idea what is wrong. Thanks for your help! Michael (1) is intended bahaviour, though I do think that the compiler could be smarter. At least the cases, that could be tail-call-optimize could also be inferred. (2) looks like a bug to me
Bug in Auto Functions and Template? Or Am I Just Crazy...
Hello all, I came across some weird behaviors yesterday and I can't figure out what it's about. (1) auto factorial(int n) { if (n < 2) return 1; return n * factorial(n-1); } The compiler complained about "forward declaration of factorial". If I change the return type to int, the problem goes away. I can understand that with the recursion, it might be impossible for the compiler to deduce the type of factorial and so it compile errors, but I don't see anything about that on the Language Reference. Is this the intended behavior? (2) auto stuff(T)(T[] arr) { auto inner(T[] s) { s[0] = 0; } arr.inner(); } This time the compiler complained about 'inner' not being defined. This time I have no idea what is wrong. Thanks for your help! Michael