calmm-js / partial.lenses

Partial lenses is a comprehensive, high-performance optics library for JavaScript
MIT License
915 stars 36 forks source link

Change `L.removable` Take a Predicate? #176

Closed rjhilgefort closed 6 years ago

rjhilgefort commented 6 years ago

Is there an easy way to have L.removable remove empty arrays as well as undefined? Or perhaps the better question is how can I change the result of a L.set that does a L.find and either sets a value or undefined, to then remove the entire array if the array is empty after the removal of the value (based on a L.removable lens that targets that array prop).

My, probably naive, approach to solve the problem is to have L.removable take a predicate on which it decides to remove the object based on.

Love the library and thanks in advance for the help!

rjhilgefort commented 6 years ago

Update: I went with a L.rewrite rule coming out of my lens that gave me an array. Effectively something like:

const myValueLens = value => [
  'things',
  L.rewrite(R.when(R.isEmpty, always(undefined))),
  L.find(R.equals(value))
];

L.set(myValueLens('foo'), undefined, {
  things: ['foo']
});

This allowed a lens higher up to remove the object from the array when things was ever empty. Is this the right approach? Do I need to clarify with a more complete example?

polytypic commented 6 years ago

L.rewrite works, but L.defaults([]) is the combinator originally intended for the purpose as in this example:

const myValueLens = value => [
  'things',
  L.defaults([]),
  L.find(R.equals(value))
]

L.set(myValueLens('foo'), undefined, {
  things: ['foo']
})

Originally Partial Lenses removed empty arrays and objects by default, but that was changed in v13.0.0. The discussion in the changelog entry and issue is perhaps a bit lacking. The main reason I changed the behaviour is that while PL with default removal worked well (operations can handle undefined and empty things), other libraries and standard functions do not. I saw a lot of code using PL to manipulate some data structure and then use other libraries or standard functions to operate on the result and having potential crashes due to the PL part removing empty arrays and objects. Not having by default removal makes it easier/simpler to use PL in conjunction with other libraries.

rjhilgefort commented 6 years ago

Oh, awesome. I didn't realize the set behavior of L.defaults did that. Thanks for the response and for such a great lib/documentation. Cheers!