I'm trying to get all the rotations of the list v
. So, in the definition of rotations
, I use the flipped version of rotateLeft
as the first branching function (in order to accept the list first) and then a function that returns the list [0, 1, 2, ..., v.length-1]
, with map
as the converging function.
const {curry,mathMod,pipe,splitAt,reverse,unnest,converge,map,flip,length,times,identity} = require("ramda");
const v = [1,2,3,4];
const rotateLeft = curry((n,vet) => {
const i = mathMod(n,vet.length);
return pipe(
splitAt(i),
reverse,
unnest
)(vet);
});
const rotations = converge(map,[
flip(rotateLeft),
pipe(length,times(identity))
]);
rotations(v);
However, this doesn't return what I expected. Instead, it works fine if I rewrite that as follows:
map(flip(rotateLeft)(v),
pipe(length,times(identity))(v));
// gives [[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]]
As I understand, converge
applies the two branching functions to v
and then feeds the results as arguments to map
. Is that right?
So why doesn't rotations(v)
return the same thing?
More concise version using reduce
Inspired by your versions in vanilla JS, I've come up with the following reduceRotations
function, which doesn't use the index parameter of map
or recursion in an obvious way. Then, of course, I translated that into vanilla Ramda, in a totally point-free fashion. :)
const {converge,reduce,always,append,pipe,last,head,tail,identity,unapply} = require("ramda");
const reduceRotations = (v) => {
const rotate = (v) => append(head(v),tail(v));
return reduce(
(acc,_) => append(rotate(last(acc)),acc),
[v],
tail(v)
);
};
const pointFreeRotations =
converge(reduce,[
always(converge(append,[
pipe(last,converge(append,[head,tail])),
identity
])),
unapply(identity),
tail
]);
Yet another one
The following equivalent functions employ scan
instead of reduce
.
const {converge,scan,always,append,head,tail,identity} = require("ramda");
const scanRotations = (v) => {
const rotate = (v) => append(head(v),tail(v));
return scan(rotate,v,tail(v));
};
const scanPointFreeRotations =
converge(scan,[
always(converge(append,[head,tail])),
identity,
tail
]);