- Notifications
You must be signed in to change notification settings - Fork 104
Add indexer lens for List and Array #423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
gusty left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for contributing with this.
A few notes, in addition to my comments, could you add a test case? The code you posted on slack would be just fine, or you can add it in the docs, as the docs are also kind of tests in that they should build.
We should make sure the behavior in corner cases is the same as in other common Lens ie: what happen is I set an index out of the bounds?
This implementation is a quick'n dirty one, but maybe there's room for optimization, remember these functions will be called many times.
| BTW: Don't worry about squashing your commits, I can squash the whole stuff when merging ;) |
| I cannot begin to express my joy at hearing that 😂 |
| Brain-static from the workweek! So:
I also at least added note to them in the main docs page for Extensions. With regards to performance and optimizations, I'm flatfooted - while rudimentary, these functions are also not doing a whole lot. I'm not sure how one would immediately optimize them. Suggestions of things to explore? |
Fine, another solution would be to include the code for them in the body of
Nice !
I would say let's leave it like this, as I have no clue how could it be improved at the moment. Maybe that's the best we can do. Thanks for taking care of this, we'll include it in our coming release. It would be nice to add the example of the pages of the book in the docs, but otherwise we can do it in a separate PR. |
| May as well just do it now :) Speaking of the But that concern has abated, after the investigation and realization that Yank at least |
| Yes, go ahead and inline that function or all of them. The less functions we introduce the better, in order to keep this PR more atomic. We can always make them public in a future PR. EDIT: actually I'm a bit ambivalent, as now I remembered I encountered some situations where these functions had been very handy. Of course lens would have been better, but when you have to change something in a structure and you don't use lenses these functions provides a good alternative. So my 2 cents to keep them public ;) |
Yeah, the List functions are things that I've seen come up a few times from folks on Slack - generally beginners conflating with It's the Array one (and lens) that I would want to yank, since both
It will! And I'm going to make the case that it should. First - I will just get Second - F# inherits Array semantics from the ML family: Fixed Size, Mutable Cells. So it's not alone in this choice, and folks from sibling languages and F# in general are likely to expect that 'setting' a single value at an index in an Array will mutate that Array, not replicate with a new value at the index. That said, I see the point from the direction of pure immutability as well 😅 - and it seems like a "do one thing, and a ticket will (eventually) be filed wanting the other" situation. Since the read half of the lens is the same, having an entirely separate lens feels weird - how bad would parameterization be? |
| I think the main issue here is that if it mutates the array, the lens would also mutate the original array, which is certainly wrong. We have to fix the function, no doubt, now the question is, do we fix it and make it private, or do we make it public, aligned with the List counter part. I am a bit inclined for the latter. What do you think ? |
| The sticking point for me is that I'm not certain it is implicitly wrong - I suspect it has a lot to do with the individual examining the problem. For better or worse, Arrays are mutable, and the hinting from the standard library is that individual ( I lean somewhat - clearly - to the mutable-cells side of things: But part of that is in keeping an eye on the imminent arrival of To be clear: Happy to move to a new-array thing now, but I want to just acknowledge and make the best case I can for what makes sense to me - both from a "what is going to make sense to others" perspective as well as "what won't create the need for modifying this in the future" perspective 😅 |
| I understand the argument about "the expectation is that an array will mutate", but if we go down that road, there's little to no sense in defining a lens over an array, since a lens is something like a pure pointer. If you are ok with mutability, just mutate, why bother with lenses? |
| And this might be at the edge of my experience/understanding in these abstractions - so do correct me if my thinking is flawed here: |
| If you break lensing rules, bad things will happen, believe me :) Regarding your example, you normally compose the individual optics, without special-casing anything. |
| Just to be clear, what I mean is this: Let's imagine we need to update the first page of the If we have an array anywhere in that chain, what's the option in the case that we want such mutable semantics? We end up needing to 'special case' how we access things - since we can't easily just create such a chain of composition any longer. Or we end up writing our mutable lens anyway. |
You will never want such mutable semantic in that scenario. Doing that will be the source of many headaches. |
| Got it now 😅 |
| |> areEqual (ResizeArray ([30; 41; 34; 45; 31; 42; 35; 46])) | ||
| | ||
| [<Test>] | ||
| let ``List.setAt works with good indices`` () = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
| let lens_list_item () = | ||
| let l = [1;2;3] | ||
| areEqual (Some 2) (l ^. List._item 1 ) | ||
| areEqual None (l ^. List._item 3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice to see some simple tests of the code 😃
gusty left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks one more time for taking care of this.
| Thanks for the opportunity and the discussion, I feel illuminated :) |
Noticed this hadn't been added after the discussion the other day - so here it is.
I've added an Array module for the same behavior - but with slightly differing semantics owing to the nature of Array.