Reputation: 20560
Not grasping the functional solution to this. I'm specifically working with ramda.js
, but I believe the problem applies to any functional language.
Looking to return a new list with a head that is a modified copy of the existing head, then map over the entire list after the substitution has been made. I want to do special/extra logic for the head of the list when mapping over the list.
Here's a pseudo-code:
R.compose(
R.map(mapsValuesToDOMNodes), // <-- ex. returns radio buttons, with the first one
// selected, from previous "isFirst" prop
// <-- ??? "modify" the head of the list; ex., add "isFirst" prop
R.sortBy(aPropInEachValue),
R.values
)(myObj);
NOTE: I'm hopefully looking for a language-agnostic solution, and I want to understand the functional approach to this problem.
Upvotes: 1
Views: 83
Reputation: 2308
This may be the example you are looking for:
var x = [{a: 1}, {a: 2}, {a: 3}, {a: 4}];
var headLens = R.lens(
R.head,
R.converge(R.prepend, [R.identity, R.flip(R.tail)])
);
var f = R.pipe(
R.over(headLens, R.assoc("isFirst", true)), //use the lens to work only on the head
R.map(R.evolve({a: R.add(2)})) //map through the entire list
);
var y = f(x);
console.log(y); // [{"a": 3, "isFirst": true}, {"a": 4}, {"a": 5}, {"a": 6}]
<script src="//cdn.jsdelivr.net/ramda/latest/ramda.min.js"></script>
What is going on here is that a lens is created with a setter that prepends the new head value to the tail of the old list.
If javascript had pattern matching then it would be much easier. Here's an example, in F#, that applies a function to only the head and returns a list with the function result as new head.
let mapHead f (h::t) = f h :: t //described function
let l = [1;2;3;4] //declare list of 4 ints
let r = mapHead ((+) 2) l //add 2 to head and return entire list
r //[3;2;3;4]
Upvotes: 0
Reputation: 433
You can could use either R.lensPath or R.assocPath
R.assocPath([0, 'isFirst'], true);
Upvotes: 0
Reputation: 4540
I'm not sure about with rambda.js
, but functionally I think the concept would be to extract the head and tail (uncons
), then apply a function to the head and cons
it to the mapped tail.
In Haskell, something like:
applyFirstAndMap :: (a -> b) -> (a -> b) -> [a] -> [b]
applyFirstAndMap _ _ [] = []
applyFirstAndMap fx fxs (x:xs) = fx x:map fxs xs
And then:
applyFirstAndMap (+ 1) (+ 2) [1,2,3] == [2,4,5]
Upvotes: 2