ramda-adjunct icon indicating copy to clipboard operation
ramda-adjunct copied to clipboard

lensSlice

Open wojpawlik opened this issue 7 years ago • 6 comments

Is your feature request related to a problem? Please describe. Python-style pure slice and set slice encapsulated in a lens.

Describe the solution you'd like

const lensSlice = (bgn, end) => R.lens(
    R.slice(bgn, end),
    (value, target) =>  R.useWith(
      R.apply(RA.concatAll), 
      [RA.sliceTo(bgn), R.identity, RA.sliceFrom(end)]
    )(oldVal, newVal, oldVal)

Describe alternatives you've considered

--

Additional context

Original comment of the issue author: Python-style pure slice and set slice encapsulated in a lens:

const lensSlice = (bgn, end) => R.lens(
    R.slice(bgn, end),
    (newVal, oldVal) => oldVal.slice(0, bgn).concat(newVal).concat(oldVal.slice(end)))

Probably it could be rewritten to be more readable, but it's just proof-of-concept.

Example:

const lens = lensSlice(0, 2)
R.set(lens, '1212', 'aasdf') //=> "1212sdf"

Python for comparison (used list because strings are immutable, and set slice is mutating IIRC):

>>> a = list('aasdf')
>>> a[0:2] = '1212'
>>> a
['1', '2', '1', '2', 's', 'd', 'f']
R.set(lens, Array.from('1212'), Array.from('aasdf')) //=> ["1", "2", "1", "2", "s", "d", "f"]

wojpawlik avatar Feb 20 '18 21:02 wojpawlik

Related: https://github.com/calmm-js/partial.lenses#L-prefix https://github.com/calmm-js/partial.lenses#L-slice

wojpawlik avatar Feb 20 '18 22:02 wojpawlik

Legitimate; but I would simplify the composition and use already established tools for that

const lensSlice = (bgn, end) => R.lens(
    R.slice(bgn, end),
    (value, target) =>  R.useWith(
      R.apply(RA.concatAll), 
      [RA.sliceTo(bgn), R.identity, RA.sliceFrom(end)]
    )(oldVal, newVal, oldVal)

Ref https://www.linkedin.com/pulse/functional-lenses-javascript-vladim%C3%ADr-gorej/ for naming Ref concatAll need to implemented first to allow this composition

char0n avatar Feb 21 '18 06:02 char0n

We could also define setSlice:

const setSlice = R.curry((bgn, end, replacement, target) =>
    RA.concatAll([RA.sliceTo(bgn, target), replacement, RA.sliceFrom(end, target)]))

// Then
const lensSlice = R.curry((bgn, end) => R.lens(R.slice(bgn, end), setSlice(bgn, end)))
// const lensSlice = R.converge(R.lens, [R.slice, setSlice]) // doesn't work

And perhaps using fromIndex instead of bgn and toIndex instead of end would be a good idea (R.slice uses those names).

I'd tackle this after concatAll.

wojpawlik avatar Feb 21 '18 11:02 wojpawlik

Create a separate issue for setSlice. See the R.adjunct before doing so. I'd go for a name adjustSlice instead of setSlice.

char0n avatar Feb 21 '18 11:02 char0n

I don't think opening an issue is necessary, I don't think it needs discussion. Except name, for which I suggest updateSlice, because it's more akin to R.update than R.adjust.

wojpawlik avatar Feb 23 '18 11:02 wojpawlik

@GingerPlusPlus We create a separate issue for each function (except where two are basically inversions of each other), so please open a new issue for RA.updateSlice so it can be discussed separately.

Undistraction avatar Feb 23 '18 12:02 Undistraction