zl程序教程

您现在的位置是:首页 >  其它

当前栏目

[Ramda] Refactor to Point Free Functions with Ramda using compose and converge

to and with Using Compose free point Functions
2023-09-14 09:00:52 时间

In this lesson we'll take some existing code and refactor it using some functions from the Ramda library, most notably, compose and converge. When we're done, we'll have taken a function with a couple of local variables and parameter references and converted it into more streamlined "point-free" or "tacit" functions.

 

For example, we have following function:

const R = require('ramda');

const person = {
    id: 1,
    name: 'Joe'
};

const generateUrl = (id) => `http://img.soicalnetwork.com/avatar/${id}.png`;
const getUpdatedPerson = (person) => {
    const url = generateUrl(person.id);
    return R.assoc('avatar', url, person);
}  
const result = getUpdatedPerson(person);

It will add a 'avatar' prop to person object.

 

We want to refactor the code to make it point free style, we the functions can be more reuseable and easy to understand.

First try:

//===============================================
// #1 Refactoring
//===============================================
/*
 Solve the problem that when id is undefined, we need a default image
 Solution: propOr('defaultValue', 'prop')
 */

const generateUrl = (id) => `http://img.soicalnetwork.com/avatar/${id}.png`;
const getUpdatedPerson = (person) => {
    const url = generateUrl(R.propOr('default', 'id')(person));
    return R.assoc('avatar', url, person);
}  
const result = getUpdatedPerson(person);
console.log(result);

Here we use 'R.propOr', to get prop of an object and set default fallback value. This can help us prevent undefined problem.

 

Second try:

//===============================================
// #2 Refactoring
//===============================================
/**
 * Extra a single function to get Person url.
 * Solution: Here we using R.compose.
 * SO getURLFromPerson is point-free function.
 */

const generateUrl = (id) => `http://img.soicalnetwork.com/avatar/${id}.png`;
const getURLFromPerson = R.compose(
    generateUrl,
    R.propOr('default', 'id')
);
const getUpdatedPerson = (person) => R.assoc('avatar', getURLFromPerson(person), person);
const result = getUpdatedPerson(person);
console.log(result);

Here we use 'R.compose' to make 'getURLFromPerson' as a point-free function. Notice in the function, we no longer need to pass 'person' object as a param.

 

Third try:

//===============================================
// #3 Refactoring
//===============================================
/**
 * In getUpdatedPerson function, we still relay on the 'person' param we pass in.
 * We want to make it a point-free function also.
 * Solution: we can use R.converge
 */
const generateUrl = (id) => `http://img.soicalnetwork.com/avatar/${id}.png`;
const getURLFromPerson = R.compose(
    generateUrl,
    R.propOr('default', 'id')
);
// const getUpdatedPerson = (person) => R.assoc('avatar', getURLFromPerson(person), person);
const getUpdatedPerson = R.converge(
    R.assoc('avatar'),
    [
        getURLFromPerson,
        R.identity
    ]
)
const result = getUpdatedPerson(person);
console.log(result);

The old verson of 'getUpdatedPerson' relay on 'person' param, to make it as point-free function style, we can use another way 'R.converge'.