Javascript can flatten an array:
const nesting = 2;
const arr = [0,[1,[2,3]]].flat(nesting);
console.log(arr);
//output
[0,1,2,3]
It all makes sense because a Javascript array can hold data of mixed types. Can this be expressed using C ranges ? Is it possible to nest ranges in this way ?
What about if you want to flatten a vector of vectors:
const vector<vector<int> > vv={{0,1},{2,3}};
auto rg = vv | views::flat;
Is there such a function in the pipeline ?
CodePudding user response:
It's named ranges::views::join
and it flattens a range of ranges into a range. (For flattening more layers, you need to join
multiple times.)
To be precise, ranges::views::join
is the thing that together with ranges::views::single
and ranges::views::transform
allows you to treat ranges as the monads they are.
This is however different from JavaScript's .flat(n)
, which can flatten array which contains elements which are arrays and not arrays.
So JavaScript's .flat
has a much looser meaning than views::join
, in the sense that it accomplishes what join
does, but other things as well, which don't make much sense in functional programming, at least not as regards join
.
As noted in a comment, flattening all elements of an array such as the one in the question's JavaScript snippet can have sense. But that is an operation that does not belong to the list monad. Monads can be defined in terms of monadic binding (>>=
Haskell, and, for just the list monad, transform(id) | join
in C with Range-v3) and a constructor (return
or pure
in Haskell, and, for just the list monad, ranges::views::single
in C with Range-v3). These tools alone don't allow one to flatten a tree in a list (see this for what the tree monad is). That's an operation that can be accomplished via folding.
So the bottom line of the above paragraph is:
- if you are looking for the behavior that
.flat(n)
exhibits on "uniformly nested" arrays (invented terminology which I hope is obvious by now), thenranges::views::join
is there for you; - if you are looking for the behavior it exhibits more in general, then you need to invoke the full power of folding, that in C goes by the name of
std::for_each
/ranges::for_each
(I'm assuming you have a way to iterate on the structure, i.e. your structure has.begin()
and.end()
memebrs, i.e. it is a range).
CodePudding user response:
const vector<vector<int> > vv={{0,1},{2,3}};
auto rg = vv | views::join;
//rg={0,1,2,3}
const vector<vector<vector<int> > > vv={
{{0,1},{2,3}},
{{4,5},{6,7}}
};
auto rg = vv | views::join | views::join;
//rg={0,1,2,3,4,5,6,7,8}