Re: array inside a class + alias this + filter -> clears the array.

2021-07-07 Thread realhet via Digitalmars-d-learn

On Wednesday, 7 July 2021 at 17:10:01 UTC, Paul Backus wrote:

On Wednesday, 7 July 2021 at 16:20:29 UTC, realhet wrote:



int[] opIndex() { return array; }


Thx, I didn't know about this type of opSlice override. It works 
nicely.


Now I have these choices:
- write [] everywhere to access the containers.
- write nothing extra to access the containers but put the 
container operations one level higher and select the container 
for those based on a dummy struct.


Like going from:
```
db.entities.add("Entity01");
to
db.add(entity("Entity01"));   //struct entity{ string name; }
```

Currently I have both ways plus your solution for the range 
access.


Gotta experience with it to choose.

Thanks again! I will remember that common container rule from now 
on.


Re: array inside a class + alias this + filter -> clears the array.

2021-07-07 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 7 July 2021 at 16:20:29 UTC, realhet wrote:

Hi,

I wanted to make a container class that exposes its elements 
using a simple "alias this", but getting weird errors:


I test with the std.algorithm.filter template function.

1. when I use "alias this" on a function that returns a slice, 
making the internal array unreachable, filter just can't 
compile.
2. when I expose the array as it is, filter deletes the array 
after it returns.


My goal is to make a class, which acts like an array, but also 
having member functions to add/remove/find its items. On top of 
that this class has an owner (a database table thing) too.


In general, it is not a good idea to have your container class 
also function as a range, for exactly this reason. Instead, your 
container class should have a method that returns a range over 
its elements, with the range being a separate object.


The conventional way to do this is to overload `opIndex`:

```d
class C
{
private int[] array;
this(int[] array) { this.array = array; }
int[] opIndex() { return array; }
// etc.
}

void main()
{
import std.algorithm;

auto c = new C([1, 2, 3]);
c[].filter!"true".each!writeln;
assert(c[].length == 3);
}
```


array inside a class + alias this + filter -> clears the array.

2021-07-07 Thread realhet via Digitalmars-d-learn

Hi,

I wanted to make a container class that exposes its elements 
using a simple "alias this", but getting weird errors:


I test with the std.algorithm.filter template function.

1. when I use "alias this" on a function that returns a slice, 
making the internal array unreachable, filter just can't compile.
2. when I expose the array as it is, filter deletes the array 
after it returns.


My goal is to make a class, which acts like an array, but also 
having member functions to add/remove/find its items. On top of 
that this class has an owner (a database table thing) too.


Example use-cases:
table.rows.add(...)
table.rows[4]
table.rows.filter!(...).map!(...)


```
import std.stdio, std.range, std.algorithm, std.uni, std.utf, 
std.conv, std.typecons, std.array, std.traits, std.exception, 
std.format, std.random, std.math;


class C{ //must be a class, not a struct
int[] array;

static if(0){
   //BAD: filter cannot deduce from an aliased function
   // that returns a nonref array
  auto getArray(){ return array; }
  alias getArray this;
}else{
  alias array this; //this works
}
}

void main(){
auto c = new C;
c.array = [1, 2];

void wl(){ writeln("len=", c.length); }

//filtering the array explicitly: GOOD
c.array.filter!"true".each!writeln; wl;

//filtering the slice of the alias: GOOD
c.array.filter!"true".each!writeln; wl;

//filtering the alias: BAD -> erases the array
c.filter!"true".each!writeln; wl;
}
```


Thanks in advance.