Re: Filtering a tuple of containers with indices

2015-11-17 Thread anonymous via Digitalmars-d-learn

On 17.11.2015 15:32, maik klein wrote:

template tupIndexToRange(alias Tup, Indices...){

[snip]

I don't quite understand how that code is supposed to work. Maybe 
there's just some detail missing, but it could also be that your 
approach can't work.



This is roughly what I want to achieve

   alias Integrals = AliasSeq!(Array!int, Array!float, Array!double);
   Integrals integrals;
   integrals[0].insertBack(1);
   integrals[1].insertBack(2);
   integrals[2].insertBack(3);

   auto range = zip(tuple(integrals[0][],integrals[1][]).expand);
   writeln(range);
   foreach(e;range){
 writeln("element: ",e);
   }
But instead of "auto range =
zip(tuple(integrals[0][],integrals[1][]).expand);" I want it to be
generic "auto range = zip(tupIndexToRange!(integrals, AliasSeq!(0,
1)).expand);"


I think the problem can be split up into two independent tasks:

1) Select fields of a tuple by indices (to drop `integrals[3]`).
2) A "map" function for tuples (to apply `[]` to the selected arrays).

Here are two quick implementations of those applied to your problem:


template selectFromTuple(indices ...)
{
auto selectFromTuple(Types...)(Types values)
{
import std.typecons: tuple, Tuple;
static if (indices.length == 0) return Tuple!()();
else
{
enum headIndex = indices[0];
auto tail = .selectFromTuple!(indices[1 .. $])(values);
return tuple(values[headIndex], tail.expand);
}
}
}

auto mapTuple(alias op, Types ...)(Types values)
{
import std.meta: staticMap;
import std.typecons: tuple;

alias ResultType(T) = typeof(op(T.init));
alias ResultTypes = staticMap!(ResultType, Types);

ResultTypes results;
foreach (i, v; values) results[i] = op(v);
return tuple(results);
}

void main()
{
  import std.container.array;
  import std.meta: AliasSeq;
  import std.range: zip;
  import std.stdio: writeln;

  alias Integrals = AliasSeq!(Array!int, Array!float, Array!double);
  Integrals integrals;
  integrals[0].insertBack(1);
  integrals[1].insertBack(2);
  integrals[2].insertBack(3);

  auto range = integrals
.selectFromTuple!(0, 1).expand
.mapTuple!(a => a[]).expand
.zip;

  writeln(range);
  foreach(e;range){
writeln("element: ",e);
  }
}


That looks a lot like range based programming, which makes me think that 
there could be a way to use actual range algorithms from std.algorithm 
for this. But I don't see how.


Filtering a tuple of containers with indices

2015-11-17 Thread maik klein via Digitalmars-d-learn

The question is also posted on

https://stackoverflow.com/questions/33757981/filtering-a-tuple-of-containers-with-indicies


template tupIndexToRange(alias Tup, Indices...){
  import std.meta;
  static if(Indicies.length == 0){
alias tupIndexToRange = AliasSeq!();
  }
  else{
alias tupIndexToRange = AliasSeq!(Tup[ Indices[0] ][], 
tupIndexToRange!(Tup,Indices[1..$]));

  }
}

void main{
  alias Integrals = AliasSeq!(Array!int, Array!float, 
Array!double);

  Integrals integrals;

  alias IntegralRange = tupIndexToRange!(integrals,0,1);
}

void main{
  alias Integrals = AliasSeq!(Array!int, Array!float, 
Array!double);

  Integrals integrals;

  alias IntegralRange = tupIndexToRange!(integrals,0,1);
}

I want to achieve something like this

auto range = zip(tupIndexToRange!(integrals,0,1));

I think the main problem is that Tup[ Indicies[0] ] doesn't work, 
to me it should have expanded to this 
AliasSeq!(itegrals[0][],integrals[1][]);



This is roughly what I want to achieve

  alias Integrals = AliasSeq!(Array!int, Array!float, 
Array!double);

  Integrals integrals;
  integrals[0].insertBack(1);
  integrals[1].insertBack(2);
  integrals[2].insertBack(3);

  auto range = zip(tuple(integrals[0][],integrals[1][]).expand);
  writeln(range);
  foreach(e;range){
writeln("element: ",e);
  }
But instead of "auto range = 
zip(tuple(integrals[0][],integrals[1][]).expand);" I want it to 
be generic "auto range = zip(tupIndexToRange!(integrals, 
AliasSeq!(0, 1)).expand);"


Maybe I need use mixins?


Re: Filtering a tuple of containers with indices

2015-11-17 Thread maik klein via Digitalmars-d-learn

On Tuesday, 17 November 2015 at 15:48:10 UTC, anonymous wrote:

On 17.11.2015 15:32, maik klein wrote:

[...]

[snip]

I don't quite understand how that code is supposed to work. 
Maybe there's just some detail missing, but it could also be 
that your approach can't work.


[...]


Thanks but I have one question.

.selectFromTuple!(0, 1).expand

Does this result in a copy? I avoided doing it like this because 
I was worried that I would copy every array. But I also don't 
fully understand when D will copy.



Also doing

  foreach(e;range){
e[0] = 10;
e[1] = 10.0f;
writeln("element: ",e);
  }
  foreach(e;range){
writeln("element: ",e);
  }

doesn't mutate the range at all.



Re: Filtering a tuple of containers with indices

2015-11-17 Thread anonymous via Digitalmars-d-learn

On 17.11.2015 20:46, maik klein wrote:

.selectFromTuple!(0, 1).expand

Does this result in a copy? I avoided doing it like this because I was
worried that I would copy every array. But I also don't fully understand
when D will copy.


Yes and no. It copies the Array structs, but it does not copy the 
elements of the arrays. If I remember correctly, std.container.Array 
uses reference counting, and copying them should be cheap.


By the way, do you have a good reason to go with Array!int rather than 
int[]? They're similar, but the builtin int[] may be easier to handle.



Also doing

   foreach(e;range){
 e[0] = 10;
 e[1] = 10.0f;
 writeln("element: ",e);
   }
   foreach(e;range){
 writeln("element: ",e);
   }

doesn't mutate the range at all.


You need to mark the `e` as `ref`: `foreach(ref e; range)`. Otherwise, 
it's a copy of the element, and any changes to it are forgotten at the 
end of the iteration.


But even with `ref` it doesn't work. Seems to be a bug in or a 
limitation of `zip`. Works with `lockstep`:


  auto ranges = integrals
.selectFromTuple!(0, 1).expand
.mapTuple!(a => a[]).expand;
  auto range = ranges.zip;

  import std.range: lockstep;
  foreach(ref e0, ref e1; lockstep(ranges)){
e0 = 10;
e1 = 10.0f;
  }
  foreach(e;range){
writeln("element: ",e);
  }