Re: Passing and returning arguments by ref

2023-03-03 Thread Ali Çehreli via Digitalmars-d-learn

On 3/3/23 12:45, Joe wrote:

> I had tried changing B.x1() to:
>
>`ref X x1() { return [0]; }`
>
> but the compiler didn't accept it.

Yeah, that wouldn't work because the return expression is an X*.

Even though 'ref' is implemented as a pointer behind the scenes, that 
syntax is not legal.


> It's a bit weird that by taking the address of calling B.x1() and thus
> getting an X*

Agreed but that's how it is. Taking the address of a reference produces 
an X*.


> I had to *dereference* that to pass it to the helper
> function of A.mfd() which actually takes a `ref C` argument.

Yep, all of that makes sense. :)

Ali



Re: Passing and returning arguments by ref

2023-03-03 Thread Joe via Digitalmars-d-learn

Thanks, Ali.

On Friday, 3 March 2023 at 18:09:01 UTC, Ali Çehreli wrote:

Think may be due to D not having reference variables. Sometimes 
one needs to use pointers.


Ah! I'm about five chapters away from Pointers ;-).

Actually, I had tried changing B.x1() to:

  `ref X x1() { return [0]; }`

but the compiler didn't accept it.

It's a bit weird that by taking the address of calling B.x1() and 
thus getting an X*, I had to *dereference* that to pass it to the 
helper function of A.mfd() which actually takes a `ref C` 
argument.


Re: Passing and returning arguments by ref

2023-03-03 Thread Ali Çehreli via Digitalmars-d-learn

On 3/3/23 06:03, Joe wrote:

> My understanding was that since A, B and X[] are all reference types,
> this ought to work, but obviously something is missing.

Think may be due to D not having reference variables. Sometimes one 
needs to use pointers.


I find the following a simpler (and complete ;) ) example. foo() returns 
by ref and indeed, the change made to its return value is visible in main.


However, the same foo() is later called to initialize hopefullyRef but 
not the change made to that variables is not reflected in the array. (By 
the way, the example could be written without an array as well.)


struct S {
int i;

void change() {
++i;
}
}

ref S foo(S[] arr) {
return arr[0];
}

void main() {
auto arr = [ S(1) ];

// Ok, this operation changes arr[0]
foo(arr).change();
assert(arr[0].i == 2);

// This one changes the local variable
auto hopefullyRef = foo(arr);
hopefullyRef.change();
assert(hopefullyRef.i == 3);

// The array is still 2
assert(arr[0].i == 2);
}

hopefullyRef in just an int. The following definition of the 
hopefullyRef variable would cause the array element be changed:


// Now an S* (note & on the rigth-hand side)
auto hopefullyRef = (arr);
// Now hopefullyRef is an S*, not an S

// Same as before
hopefullyRef.change();
assert(hopefullyRef.i == 3);

// Now the array is affected (3, not 2)
assert(arr[0].i == 3);

Ali



Passing and returning arguments by ref

2023-03-03 Thread Joe via Digitalmars-d-learn
Let's say we have two classes, A and B.  The latter has a dynamic 
array of X and type X has an add() method that can be used to 
append elements (of type C, another struct) to X's own dynamic 
array of C.  So it's something like the following:


```d
struct C {}
struct X { C[] cs;
  void add(C c) { cs ~= c; }
}

class A {
  X x;
  void mfd(ref B b) {
 // manipulate A.x and one B.xs (returned by B.x1()
 // by calling another member function
 // that calls X.add(some C)
  }
}

class B {
  X[] xs;
  this() { xs.length = 1; }
  ref X x1() { return xs[0]; }
}
```

After A and B are instantiated and A.mfd() is called, the changes 
to A.x are visible in main.  However, although the changes to the 
X returned by B.x1() are visible while A.mfd() executes, the 
B.xs[0] is unchanged after it returns.


My understanding was that since A, B and X[] are all reference 
types, this ought to work, but obviously something is missing.