Closed ivan-kleshnin closed 7 years ago
Yes, the documentation could be clarified here. The template for L.pick
cannot directly be a nested object. However, you can do nested things by nesting optics. For example (see in playground):
let obj = {meta: {file: "./foo.txt", base: "foo", ext: "txt"}}
L.get(L.pick({meta: ["meta", L.props("file", "ext")]}), obj)
Don't have time to think this through right now, but there might be ways to allow for some form of nested version of L.props
to make this kind of usage nicer.
Here is a kind of nested cross of L.pick
and L.props
(try in playground):
let obj = {meta: {file: "./foo.txt", base: "foo", ext: "txt"}}
const nested = t => (I.isObject(t)
? L.pick(L.modify(L.values, (v, k) => [k, nested(v)], t))
: t)
L.get(nested({meta: {file: [], ext: []}}), obj)
You can give it an arbitrary nested template of (plain) objects whose leaf props must be lenses.
Does this seem like what you'd want and what would be a good name for this? L.pickNested
? L.pickIn
?
Wow, recursive lensing :)
I'm getting
Error: partial.lenses:
pick
expects a plain Object template.
with the last Partial.Lenses version available. Unpublished update to L.pick
?
Hmm... Note that the isObject
predicate from the infestines
library basically tests that the constructor of the given value is Object
. IOW, it doesn't just test that the given value inherits from Object.
BTW, thanks for opening this issue! I have to think about generalizing L.branch
and L.pick
(to accept nested templates) and possibly adding the new L.pickIn
(aka nested
above).
Here is a generalized (nested) branch
combinator (try in playground):
const branch = t => I.isObject(t) ? L.branch(L.modify(L.values, branch, t)) : t
L.modify(branch({x: {a: []}, y: {b: []}}),
R.negate,
{x: {a: 1, b: 2}, y: {a: 3, b: 4}})
Here is a generalized (nested) pick
combinator (try in playground):
const pick = t => I.isObject(t) ? L.pick(L.modify(L.values, pick, t)) : t
const data = {s: 1, t: 1}
const lens = pick({x: {a: "s"}, y: {b: "t"}})
R.identity({
get: L.get(lens, data),
set: L.set(lens, {x: {a: 1}, y: {b: 2}}, data)
})
Here is also the (newly proposed) generalized pickIn
combinator (try in playground):
let obj = {meta: {file: "./foo.txt", base: "foo", ext: "txt"}}
const pickIn = t => (I.isObject(t)
? L.pick(L.modify(L.values, (v, k) => [k, pickIn(v)], t))
: t)
L.get(pickIn({meta: {file: [], ext: []}}), obj)
BTW, I believe it is also time to seriously think about obsoleting L.augment
(this has been on my mind for some time already).
Hi, Vesa. Sorry for not participating – mad months at work :(
pickIn
looks like a reasonable solution.
No problem. I was also just on a tightly scheduled project and finally got some time & energy to finish the initial pickIn
implementation. Thanks for opening the issue!
Docs mention "object template of lenses" few times but it's never documented. By trial and error I figured out that currently it supports plain values and arrays but not nested values.
For example, I want to pick
meta.file
property chain from a given object.now I want to grab both
file
andext
but notbase
keeping the original nesting:I guess it's not possible with
L.pick
(because output is a product hence a plain collection), but not sure because it's unclear what "template of lenses" is.P.S.
I'm aware of a solution:
I just wondered maybe I missed a shorter option.