Search code examples
javascriptfunctional-programminglodashpointfree

How to make it point-free when there is local variable?


I have a code snippet to remove the host part from server URL in OpenAPI definition. I don't know how to make it point-free totally. (It isn't necessary to do that. But I just want to know how to.)

The difficult part to me is to get rid of the local variable idx. I read this SO and it seems that ap can solve. I didn't try because there is no ap in lodash.

const convert = _.flow([
  _.split('/'),
  (segments) => {
    const idx = _.findLastIndex(containAny(['{', '}', ':']))(segments);
    return _.drop(idx+1, segments);
  },
  _.reject(_.isEmpty),
  _.join('/'),
  path => '/' + path,
]);

Full code:

const _ = require('lodash/fp');

const urls = [
  'http://localhost:8080/petstore/v1',
  '//localhost/petstore/v1',
  '{server}/batch-service/api/batches/lwm2m/v1',
  'https://{server}/batch-service/api/batches/lwm2m/v1',
  '/batch-service/api/batches/lwm2m/v1',
  '/',
]

const containAny = patterns => str => _.some(pattern => _.includes(pattern, str), patterns);

const convert = _.flow([
  _.split('/'),
  (segments) => {
    const idx = _.findLastIndex(containAny(['{', '}', ':']))(segments);
    return _.drop(idx+1, segments);
  },
  _.reject(_.isEmpty),
  _.join('/'),
  path => '/' + path,
]);

_.map(convert)(urls);

Solution

  • In your case you need to call _.findLastIndex() on segments, and then call _.drop() on the results of the find and segments:

    drop(findLastIndex(segments))(segments)
    

    Which is equivalent to the chain combinator function:

    const chain = f => g => x => f(g(x))(x);
    

    Lodash/fp accepts all functions when using _.flow() (which is also a functional combinator), so you can create other functional combinators, and use them.

    const chain = f => g => x => f(g(x))(x);
    
    const containAny = patterns => str => _.some(pattern => _.includes(pattern, str), patterns);
    
    const findLastSegmentIndex = _.flow(
      _.findLastIndex(containAny(['{', '}', ':'])),
      _.add(1)
    )
    
    const convert = _.flow([
      _.split('/'),
      chain(_.drop)(findLastSegmentIndex),
      _.reject(_.isEmpty),
      _.join('/'),
      path => '/' + path,
    ]);
    
    const urls = [
      'http://localhost:8080/petstore/v1',
      '//localhost/petstore/v1',
      '{server}/batch-service/api/batches/lwm2m/v1',
      'https://{server}/batch-service/api/batches/lwm2m/v1',
      '/batch-service/api/batches/lwm2m/v1',
      '/',
    ];
    
    const result = _.map(convert)(urls);
    
    console.log(result);
    <script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>