digitalmars.D - SListRange, Ranges, costructors
- bearophile (75/75) Apr 11 2010 To answers a question in D.learn I've written a minimal single-linked li...
- Daniel Keep (2/2) Apr 12 2010 You don't need reset if you make the range a property of the list. Then
- bearophile (5/7) Apr 12 2010 In the List(T) code that I've shown there is a ListIterable struct and a...
- bearophile (32/40) Apr 13 2010 I've taken a look at SListRange, and it seems the p pointer is useless, ...
To answers a question in D.learn I've written a minimal single-linked list. This is one version (D2 code): import std.stdio; struct List(T) { static struct Node { T data; Node* next; this(T d, Node* p) { data = d; next = p; } } Node* lh; this(T[] arr) { foreach_reverse (el; arr) lh = new Node(el, lh); } Node* p; void reset() { p = lh; } // is reset necessary? bool empty() { return !p; } T front() { return p.data; } void popFront() { p = p.next; } /* static struct ListIterable { Node* p; bool empty() { return !p; } T front() { return p.data; } void popFront() { p = p.next; } } ListIterable opSlice() { return ListIterable(lh); } */ } void main() { List!int items = [1, 2, 3]; items.reset; foreach (x; items) write(x, " "); } This code has suggested me three questions/musings: 1) I've seen that the Node struct inside std.range.SListRange is not a static struct, is it a small bug? 2) In that List(T) I've used the Range protocol. But I've had to add a reset() function too. Isn't it useful for foreach() to call a function similar to reset() (if present) at the begin of the iteration, to set the variables necessary for the iteration? Is something like this already present with another name in the Range protocol? 3) The stack initalization of a struct has some built-in sugar, while to allocate the struct on the stack you need a this() method: struct Node { int data; Node* next; this(int d, Node* p) { data = d; next = p; } } void main() { Node n = Node(10, null); // OK Node* pn = new Node(10, null); // OK } So is it possible to add to D2 a standard costructor for the heap allocation version too, with the same syntax? (Such default costructor must be absent if any other costructor is defined in the struct/union): struct Node { int data; Node* next; } struct Foo { int data; Foo* next; this(int d, Foo* p) { data = d; next = p; } } void main() { Node* pn1 = new Node(10); // OK Node* pn2 = new Node(10, null); // OK Foo* pf = new Foo(10); // Error, standard initializer this(int) is absent. } Bye, bearophile
Apr 11 2010
You don't need reset if you make the range a property of the list. Then you would use `foreach( x ; list.elements )` or something.
Apr 12 2010
Daniel Keep Wrote:You don't need reset if you make the range a property of the list. Then you would use `foreach( x ; list.elements )` or something.In the List(T) code that I've shown there is a ListIterable struct and a opSlice() that returns it. If you uncomment that part of the code you can use foreach(x; alist[]). (I have copied this usage of opSlice() from Andrei). But the purpose of my original post was to note that with a reset() method, that foreach can call automatically (if reset() is present), we can avoid that opSlice syntax, or a method like "all" or "elements". So my purpose was to suggest a possible small idea to avoid some clutter in the code that uses the data structure :-) (Maybe Andrei will comment about this when he's back from the ACCU). Bye, bearophile
Apr 12 2010
1) I've seen that the Node struct inside std.range.SListRange is not a static struct, is it a small bug?Bug 4087. Currently it's not a bug.2) In that List(T) I've used the Range protocol. But I've had to add a reset() function too. Isn't it useful for foreach() to call a function similar to reset() (if present) at the begin of the iteration, to set the variables necessary for the iteration?I've taken a look at SListRange, and it seems the p pointer is useless, this works, and there is no need for the reset(): import std.stdio; struct List(T) { static struct Node { T data; Node* next; this(T d, Node* p) { data = d; next = p; } } Node* lh; this(T[] arr) { foreach_reverse (el; arr) lh = new Node(el, lh); } bool empty() { return !lh; } T front() { return lh.data; } void popFront() { lh = lh.next; } } void main() { List!int items = [1, 2, 3]; foreach (x; items) write(x, " "); // prints 1 2 3 writeln(); assert(items.lh); foreach (x; items) write(x, " "); // prints 1 2 3 } But I feel dumb and I don't understand, why isn't lh null at the end of the first foreach?3) The stack initalization of a struct has some built-in sugar, while to allocate the struct on the stack you need a this() method:Enhancement request 4086. Bye, bearophile
Apr 13 2010