Closed Daenyth closed 7 years ago
Just to be clear, you would expect list(new_fs)
to have the value [Foo(3, 0), Foo(4, 0)]
, right?
What I think you're asking here is for the unbound methods to be curried; e.g. for lens().set(value)
to be equivalent to lambda state: lens().set(value, state=state)
. You could then do both = lambda state: y_0(x_plus1(state))
, change both.run
=> both
, and everything else would work. That wouldn't be hard to implement and it would make lenses play nicer with other functional libraries.
One of my worries is how confusing it might be to someone who forgets to provide a state. Expecting to get a new state and receiving a function instead is a lot less clear than the current behaviour of raising an exception.
Another worry is that there are already three different ways to provide state to a lens (lens(state)
, lens().bind(state)
, and lens().get(state=state)
). It may be cleaner to remove the state keyword arg and the bind
method and have users rely solely on currying for doing late-binding.
I agree about removing the keyword in favor of currying. And yes expected values would be as you say. The reason I might suggest an explicit run method is for clarity and explicitness vs call, because as you said they can forget
In fact I think it wouldn't hurt the api to remove bound lenses entirely in favor of the curried style, although I could be wrong - I'm still new to it
On Fri, May 19, 2017, 3:34 AM ingolemo notifications@github.com wrote:
Just to be clear, you would expect list(new_fs) to have the value [Foo(3, 0), Foo(4, 0)], right?
What I think you're asking here is for the unbound methods to be curried; e.g. for lens().set(value) to be equivalent to lambda state: lens().set(value, state=state). You could then do both = lambda state: y_0(x_plus1(state)), change both.run => both, and everything else would work. That wouldn't be hard to implement and it would make lenses play nicer with other functional libraries.
One of my worries is how confusing it might be to someone who forgets to provide a state. Expecting to get a new state and receiving a function instead is a lot less clear than the current behaviour of raising an exception.
Another worry is that there are already three different ways to provide state to a lens (lens(state), lens().bind(state), and lens().get(state=state)). It may be cleaner to remove the state keyword arg and the bind method and have users rely solely on currying for doing late-binding.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ingolemo/python-lenses/issues/8#issuecomment-302631533, or mute the thread https://github.com/notifications/unsubscribe-auth/AAA5NOsdm91_dZ4ui3wYxSc5UXHf0Lalks5r7UYbgaJpZM4Nfz39 .
The latest commit (be2095e) has an implementation of this feature as I described. It was harder to implement than I'd expected, solely because mypy really didn't like the methods having different return types depending on the binding state of the Lens. Ended up splitting the bound and unbound lenses into separate classes, which changed the reprs and broke a few old doctests.
While I like the explicitness of run
, it would mean adding an extra level to indirection around stuff for no other reason than as an extra hoop to jump through.
This code ought to do what you want:
x_plus1 = lens().x + 1
y_0 = lens().y.set(0)
both = lambda state: y_0(x_plus1(state))
fs = [Foo(2, 2), Foo(3, 3)]
new_fs = map(both, fs)
You may have a point with bound lenses...
Wow, thanks for the quick turnaround. This will be really helpful for me!
Proposed api along with a motivating example:
Edit: actually the proposed api doesn't make a ton of sense, but I'd still like to be able to compose multiple setters together