www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - this is not an lvalue

reply Andrey <andrey kabylin.ru> writes:
Hello, I'm newbie in D. I'm trying to rewrite my project from C++ 
and now I get strange warning:
src/e2ml/node.d(23,22): Deprecation: this is not an lvalue
As I write the following code

void moveTo(ref Parameter parent) {
     this.p_parent.removeValue(this);
     this.p_parent = parent;
     this.updatePath();
}

How to fix it?
Dec 13 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 13 December 2016 at 15:09:10 UTC, Andrey wrote:
 void moveTo(ref Parameter parent) {
You probably don't want the `ref` there, nor likely on any other method definitions (especially check removeValue).
Dec 13 2016
next sibling parent reply kink <noone nowhere.com> writes:
On Tuesday, 13 December 2016 at 16:23:16 UTC, Adam D. Ruppe wrote:
 On Tuesday, 13 December 2016 at 15:09:10 UTC, Andrey wrote:
 void moveTo(ref Parameter parent) {
You probably don't want the `ref` there, nor likely on any other method definitions (especially check removeValue).
Assuming `Parameter` is a class and not a struct, yes. Be sure to check out the crucial distinction between the two in D (reference vs. value types, similar to C# class and struct), otherwise you won't get far.
Dec 13 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 13 December 2016 at 17:26:28 UTC, kink wrote:
 Assuming `Parameter` is a class and not a struct, yes.
Even if it is a struct, ref wouldn't make a difference here because the variable is assigned to a member, which means ref would get lost.
Dec 13 2016
parent kinke <noone nowhere.com> writes:
On Tuesday, 13 December 2016 at 17:52:21 UTC, Adam D. Ruppe wrote:
 On Tuesday, 13 December 2016 at 17:26:28 UTC, kink wrote:
 Assuming `Parameter` is a class and not a struct, yes.
Even if it is a struct, ref wouldn't make a difference here because the variable is assigned to a member, which means ref would get lost.
I should have been more precise, I meant the type of `this`, not `Parameter` (I actually assumed both would be the same). ;)
Dec 13 2016
prev sibling next sibling parent reply Andrey <andrey kabylin.ru> writes:
On Tuesday, 13 December 2016 at 16:23:16 UTC, Adam D. Ruppe wrote:
 On Tuesday, 13 December 2016 at 15:09:10 UTC, Andrey wrote:
 void moveTo(ref Parameter parent) {
You probably don't want the `ref` there, nor likely on any other method definitions (especially check removeValue).
Thanks it works, but where should I use the ref? for example in C++ I always used pointers for structs, classes in stack etc.:
 void open(const std::string &fileName) {...}
Dec 15 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 15 December 2016 at 13:59:05 UTC, Andrey wrote:
 Thanks it works, but where should I use the ref?
Only when you need it, break the habit of using it everywhere. If it is a value type and you want modifications to the variable itself be seen outside the function, use it: void foo(ref int something) { something++; } void main() { int a = 1; foo(a); assert(a == 2); } Since int is value and you want to see the change to the local outside the function, ref is used. However, notice: void foo(int[] arr) { arr[0] = 5; } void main() { int[2] a = [1, 2]; foo(a[]); assert(a[0] == 5); } No need for ref there, because the slice is already a reference to its contents. However, if I wanted to *append* to the slice and see that length change outside, ref may be appropriate. This brings me to classes: interfaces and class objects in D are already automatically pointers internally, just like slices. void foo(Object o) { /* already like Object* in C++ */ o.modify(); } void main() { Object o = new Object(); foo(o); // o has been modified } No need for ref to see changes to the object's internals outside. However, if you want to rebind the object: void foo(ref Object o) { /* now like Object** in C++ */ o = new Object(); } void main() { Object o; foo(o); // o represents the new Object } ref is needed there - this is changing the variable itself, not what is inside it. With structs, it depends on what you are doing with it - are you changing the variable itself or something inside it? And what is inside. struct Foo { int a; } That Foo acts just like int, so use or don't use ref as if it was an int. struct Foo { int[] a; } That one is just like a slice, no need to `ref` that unless you want to change the outer portion. The contents are implicitly referenced and not copied. struct Foo { int[4] a; } Well, this is a value type again, but bigger. Still, I'd say follow the same rule as plain `int` - only ref that if you need modifications to be seen outside the function. struct Foo { ubyte[1024 * 1024] oneMegabyte; } OK, you might want to ref that one just because the copy to the function may be expensive and the compiler is not necessarily going to optimize that (BUT the compiler MIGHT optimize it! If the function gets inlined and it isn't modified, it may compile to the same thing anyway. Still, I'd probably ref that myself, or wrap it up in pointers or maybe even a class for its interface.) General rule of thumb: if you are refing for performance, actually check it before and after first, ref isn't always faster.
Dec 15 2016
parent kinke <noone nowhere.com> writes:
On Thursday, 15 December 2016 at 15:29:13 UTC, Adam D. Ruppe 
wrote:
 General rule of thumb: if you are refing for performance, 
 actually check it before and after first, ref isn't always 
 faster.
But D doesn't make this easy, as it disallows rvalues to be passed by ref. It's a very common pitfall for C++ guys. `auto ref` for templates is an insufficient workaround/hack for that. On a side note, wrt. `ref isn't always faster` (due to the indirection): it's almost always faster on Windows 64, as all value types > 64 bit (excluding vectors for the vectorcall convention, but let's keep things simple) need to be passed by reference (ABI requirement). What this means and what keeps on being ignored is that passing a D value type > 64 bits by value (to allow rvalue args, although the parameter is a read-only one) yields the worst of both worlds - a bitcopy of the original argument passed by reference.
Dec 15 2016
prev sibling parent reply Andrey <andrey kabylin.ru> writes:
On Tuesday, 13 December 2016 at 16:23:16 UTC, Adam D. Ruppe wrote:
 On Tuesday, 13 December 2016 at 15:09:10 UTC, Andrey wrote:
 void moveTo(ref Parameter parent) {
You probably don't want the `ref` there, nor likely on any other method definitions (especially check removeValue).
In D, probably, I could write something like this:
 void open(in string fileName) {...}
Dec 15 2016
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 15 December 2016 at 14:05:08 UTC, Andrey wrote:
 In D, probably, I could write something like this:
 void open(in string fileName) {...}
Yes, though remember that `in` does have a specific meaning (even though the compiler rarely enforces it): it means you promise not to modify it nor keep a reference to it. So don't use `in` on anything you want to keep as a member or global variable, it is something you will just look at inside this function then let go.
Dec 15 2016