简体   繁体   中英

Converting multi-parameter function to point-free style using Ramda

Using Ramda , I am trying to convert a fairly large function into a point-free, both for educational and stylistic reasons.

The function takes 4 arguments, an ES6 map , a domainModel function that takes an object and returns an object, a key property to identify what is being set on the map, and a json property that is set on the map after being invoked by domainModel.

const setNewDomainModelOnMap = curry((map, domainModel, key, json) => map.set(key, domainModel(json)));

Right now, I've curried the function for some functional goodness, but I'd like to work with a parameter free version if possible. I've successfully gone point-free style on functions with less parameters, can't quite figure out the right angle to approach this one.

specializing functions

The whole point of currying is that it allows you to specialize the function with each parameter that is bound. This allows us to write generic functions that can be specialized in a variety of ways

 const mult = x => y => x * y const double = mult (2) const triple = mult (3) const negate = mult (-1) console.log(double(5)) // 10 console.log(triple(5)) // 15 console.log(negate(5)) // -5 

You have a function called setNewDomainModelOnMap which has a very specialized name but the function itself is extremely specific – there is nothing generic about it.

What if you wrote a generic function that could instead be specialized based on the arguments you give it?

// maybe something liek this would be better
const myfunc = set (someKey, someValue)
const updatedMap = myFunc (oldMap)

Lateral thinking

How about just set ?

The nature of your function is setting a value on a map – the fact that the value is augmented by some function domainModel doesn't mean that it has to be a parameter of your set function

const set = curry((key, value, map) =>
  map.set(key, value)
)

set(someKey, domainModel(json), someMap)
// => Map { ... }

And no, you can't remove any more points without your function turning into a disaster of nested compose calls – especially because you are wrapping a method ( map.set ) which would make preserving context much more complicated.


Ramda agrees this is useful

Ramda actually has it's own set function which operates on a Lens, some value, and some object.

var xLens = R.lensProp('x');

R.set(xLens, 4, {x: 1, y: 2});  //=> {x: 4, y: 2}
R.set(xLens, 8, {x: 1, y: 2});  //=> {x: 8, y: 2}

In light of this, you might want to name your function mapSet if you're ever worried about a naming conflict

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM