Positonic
Positonic

Reputation: 9411

Functional way to execute a sub-array with Ramda

Is there a more functional way of doing the below, perhaps with Ramda?

var time = 100;

sequenceInstruments.forEach(function(instrument){
    if(instrument.on)
    {
       playInstrument(time, instrument.duration);
    }
})

Upvotes: 1

Views: 532

Answers (3)

RIAstar
RIAstar

Reputation: 11912

I agree with @ftor: filter will allow you to compose in a more linear fashion, which leads to totally readable point-free code.

const play = pipe(
    filter(prop('on')),           // take only the instruments that are 'on'
    map(prop('duration')),        // take the duration of each of those
    forEach(playInstrument(100))  // play'm all
);

play(sequenceInstruments);

This is assuming playInstruments is curried already.

With lodash/fp's shorthands you could even do this:

const play = pipe(
    filter('on'),
    map('duration'),   
    forEach(playInstrument(100))
);

Upvotes: 1

Scott Sauyet
Scott Sauyet

Reputation: 50787

While I agree with Scott Christopher that the point-ful solution is easier to understand than any points-free version you're likely to come up with, if you are interested in developing a point-free version, and if you'd like time to be a parameter to your final function, Ramda offers a function that might help, useWith. (There's also a related function, converge useful for slightly different circumstances.) This depends upon your playInstrument function being curried:

const play = R.useWith(R.forEach, [
  playInstrument, 
  R.compose(R.pluck('duration'), R.filter(R.prop('on')))
]);

play(100, sequenceInstruments);

You can see this in action on the Ramda REPL.

Upvotes: 1

Scott Christopher
Scott Christopher

Reputation: 6516

By only utilising functions from Ramda in a point-free manner your example would look something like this.

const play = R.forEach(R.when(R.prop('on'),
                              R.compose(R.partial(playInstrument, [time]),
                                        R.prop('duration'))))
play(sequenceInstruments)

However I often think it can be better to dial it back a little, where the use of an anonymous function could perhaps make the code more readable and convey the intent more clearly.

const play = R.forEach(R.when(R.prop('on'), i => playInstrument(time, i.duration)))

play(sequenceInstruments)

Upvotes: 3

Related Questions