digitalmars.D - Reference to an object disregarding mutation - what's the trick?
- Steve Teale <steve.teale britseyeview.com> May 28 2007
- BCS <ao pathlink.com> May 28 2007
- Steve Teale <steve.teale britseyeview.com> May 29 2007
- Regan Heath <regan netmail.co.nz> May 29 2007
- Manfred Nowak <svv1999 hotmail.com> May 29 2007
- BCS <ao pathlink.com> May 29 2007
- Steve Teale <steve.teale britseyeview.com> May 30 2007
- Manfred Nowak <svv1999 hotmail.com> May 28 2007
- Regan Heath <regan netmail.co.nz> May 28 2007
- Mike Parker <aldacron71 yahoo.com> May 28 2007
- Daniel Keep <daniel.keep.lists gmail.com> May 28 2007
OK, so I'm in a typical tree situation: int n = node.parent.nodelist.length; node.parent.nodelist.length = n+1; // p.s. why can't I say node.parent.nodelist.length++ - doesn't work // other fluff with node.parent.nodelist node.parent.nodelist[n] = x; For brevity I want to be able to say: Node[] t = node.parent.nodelist; int n = t.length; t.length = n+1; ..... But as soon as I modify t it becomes a separate object. OK, I can use with, but how do I get the semantics I'd get with a plain old pointer to the object?
May 28 2007
Reply to Steve,OK, so I'm in a typical tree situation: int n = node.parent.nodelist.length; node.parent.nodelist.length = n+1; // p.s. why can't I say node.parent.nodelist.length++ - doesn't work // other fluff with node.parent.nodelist node.parent.nodelist[n] = x; For brevity I want to be able to say: Node[] t = node.parent.nodelist; int n = t.length; t.length = n+1; ..... But as soon as I modify t it becomes a separate object. OK, I can use with, but how do I get the semantics I'd get with a plain old pointer to the object?
you may be running into the issue that changing an array length can cause it to reallocate. I'd have to see more implementation to give you more useful information.
May 28 2007
BCS Wrote:Reply to Steve,OK, so I'm in a typical tree situation: int n = node.parent.nodelist.length; node.parent.nodelist.length = n+1; // p.s. why can't I say node.parent.nodelist.length++ - doesn't work // other fluff with node.parent.nodelist node.parent.nodelist[n] = x; For brevity I want to be able to say: Node[] t = node.parent.nodelist; int n = t.length; t.length = n+1; ..... But as soon as I modify t it becomes a separate object. OK, I can use with, but how do I get the semantics I'd get with a plain old pointer to the object?
you may be running into the issue that changing an array length can cause it to reallocate. I'd have to see more implementation to give you more useful information.
OK, here's the full story. // This is the original, and works Node node = findnode(a); // sets findex to found node if (node == null) return false; Node newnode = clone_node(node); int n = node.parent.nodelist.length; node.parent.nodelist.length = n+1; if (findex == n-1 || findex == -1) { node.parent.nodelist[n] = newnode; } else { for (int i = n; i > findex; i--) node.parent.nodelist[i] = node.parent.nodelist[i-1]; node.parent.nodelist[findex] = newnode; } // But its a pain to type and read. What I wanted to do was // simplify it. My choices appear to be: // This works Node* pnl = &node.parent.nodelist[0]; if (findex == n-1 || findex == -1) { pnl[n] = newnode; } else { for (int i = n; i > findex; i--) pnl[i] = pnl[i-1]; pnl[findex] = newnode; } OR // This works with (node.parent) { int n = nodelist.length; nodelist.length = n+1; if (findex == n-1 || findex == -1) { nodelist[n] = newnode; } else { for (int i = n; i > findex; i--) nodelist[i] = nodelist[i-1]; nodelist[findex] = newnode; } } OR // This won't compile - it compiles with in, out, and lazy void insertNode(ref Node[] nl, Node nn) { int n = nl.length; nl.length = n+1; if (findex == n-1 || findex == -1) { nl[n] = newnode; } else { for (int i = n; i > findex; i--) nl[i] = nl[i-1]; nl[findex] = newnode; } } insertNode(node.parent.nodelist, newnode); OR // Aliasing would be nice, but does not work in this context alias node.parent.nodelist pnl; int n = pnl.length; pnl.length = n+1; if (this.findex == n-1) { pnl[n] = newnode; } else { for (int i = n; i > findex; i--) pnl[i] = pnl[i-1]; pnl[findex] = newnode; } The version with the Node* is the tightest, but I don't reaaly find any of the approaches satisfying.
May 29 2007
You can replace your for loop with a memmove call, heres some code to chew on:
import std.stdio, std.random;
extern(C) void *memmove(void *,void *,size_t);
struct Node { int x; }
Node[] nodeList;
static this()
{
nodeList.length = 10;
foreach(i, ref n; nodeList) n.x = i*2;
printNodes(nodeList);
}
uint findNode(Node[] nodeList, ref Node nn)
{
foreach(i, n; nodeList) { if (n.x > nn.x) return i; }
return nodeList.length;
}
void insertNode(ref Node[] nodeList, ref Node nn)
{
int i = findNode(nodeList,nn);
nodeList.length = nodeList.length + 1;
if (i < nodeList.length-1) {
memmove(&nodeList[i+1], &nodeList[i],
Node.sizeof * (nodeList.length-i-1));
}
nodeList[i] = nn;
}
void printNodes(Node[] nodeList)
{
foreach(i, n; nodeList) {
writef(n.x,(i<nodeList.length-1)? "," : "\n");
}
}
void randomNode(ref Node[] nodeList)
{
Node nn;
nn.x = rand()%20;
writefln("ADD:",nn.x);
insertNode(nodeList,nn);
}
void main()
{
randomNode(nodeList);
randomNode(nodeList);
randomNode(nodeList);
randomNode(nodeList);
printNodes(nodeList);
}
Regan Heath
May 29 2007
Steve Teale wroteOK, here's the full story.
What clumsy data structure might be organized by that? That seems to be arr= arr[ 0 .. findex] ~ newnode ~ arr[ findex .. arr.length]; and nothing more. -manfred
May 29 2007
Reply to Manfred,Steve Teale wroteOK, here's the full story.
That seems to be arr= arr[ 0 .. findex] ~ newnode ~ arr[ findex .. arr.length]; and nothing more. -manfred
yes that is what it seems to be, however, it skips the guarantied reallocation of the cat version
May 29 2007
Manfred Nowak Wrote:Steve Teale wroteOK, here's the full story.
What clumsy data structure might be organized by that? That seems to be arr= arr[ 0 .. findex] ~ newnode ~ arr[ findex .. arr.length]; and nothing more. -manfred
Fair comment - I'm clearly still thinking somewhere back in C!
May 30 2007
Steve Teale wrotehow do I get the semantics I'd get with a plain old pointer to the object?
You cannot use?: Node[]* t = &node.parent.nodelist; -manfred
May 28 2007
Manfred Nowak Wrote:Steve Teale wrotehow do I get the semantics I'd get with a plain old pointer to the object?
You cannot use?: Node[]* t = &node.parent.nodelist;
Manfreds rather brief reply is exactly what I was going to suggest. The nice thing about D is that a struct, class, pointer, reference, pointer to pointer or reference, pointer to pointer to .. you get the idea; all get de-referenced by the '.' operator, there is no silly '->' operator for pointers. So, by taking a pointer to the reference you should be able to modify the reference via the pointer by saying: int n = t.length; t.length = n+1; or t.length = t.length+1; Regan Heath
May 28 2007
Steve Teale wrote:For brevity I want to be able to say: Node[] t = node.parent.nodelist; int n = t.length; t.length = n+1; ..... But as soon as I modify t it becomes a separate object.
No, it doesn't become a separate object when you modify it, it does so when you declare it. Arrays are objects that consist of a length field and a data pointer. Consider this line: Node[] t = node.parent.nodelist; What happens here is that t is, internally, a new array object which has the same length as and points to the same data as node.parent.nodelist. So when you modify t's length, you are modifying the new object and not the original.OK, I can use with, but how do I get the semantics I'd get with a plain old pointer to the object?
Your choices are to either use with as you mention or, as Manfred suggested, use a pointer to the original array object.
May 28 2007
Your other problem's been addressed, but I just wanted to comment on Steve Teale wrote:OK, so I'm in a typical tree situation: int n = node.parent.nodelist.length; node.parent.nodelist.length = n+1; // p.s. why can't I say node.parent.nodelist.length++ - doesn't work
This is probably one of big warts with properties in D. An array's ".length" isn't just a data field. Because assigning to it can cause other things to happen (like a reallocation), it's a property. And because of the way properties are implemented in D, they cannot act as lvalues. Short version: You can't ++, --, op= a property, or pass it by reference. If you're still wondering what the difference is: struct LengthIsAField { size_t length; } struct LengthIsAProperty { size_t length() { ... } size_t length(size_t value) { ... } } Both are accessed using "instance.length", but the latter can't be used as an lvalue. Hope that helps :) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 28 2007









Regan Heath <regan netmail.co.nz> 