Hi José, I have considered that as one possibility too. From Eric's comments I don't belive the Access module is the correct place to implement it though. Personally, I don't care what the module is called because I am prepared to create my own module to handle this.
What I find curious is that once we implement Kernel.nillable_get_in, why would anyone choose to use Kernel.get_in instead? Who wants to opt into nil-exceptions (Tony Hoare's billion dollar mistake)? We have other means, such as the dot syntax (my_struct.atom_key.sub_key) when we have confidence those keys exist and we want to "let it fail" if they don't. Kernel.get_in should be used only when we have tentative expectations of a data structure. I use this when dealing with untrusted 3rd party json data on the edge of my system. Some fields that typically should be a list might be missing or present but nil until some state transition and they transition to an explicit field with a list value that Access.at can traverse. I accept the argument that only something new like nillable_get_in is backwards compatible, but I wonder how valuable the backwards compatible get_in implementation is. There is support in this thread for mil-safety (or nil-ignorance as once presented) by default. I'm left wondering how many production systems rely upon nil exceptions during Kernel.get_in calls for proper behavior that would fail if we made it nil-safe by default. -Greg Vaughn > On Feb 7, 2020, at 4:40 PM, José Valim <jose.va...@dashbit.co> wrote: > > Hi Greg, I have been thinking more about this too, and I think there are some > neat ways we can make this more accessible: > > We could introduce Access.nillable (please suggest a better name) that you > would use like this: > > get_in(root, Access.nillable([:foo, :bar, Access.at(0)])) > > Basically, it traverses the path and sets all functions in the path to > something that handles nil. In your apps, you can quickly encapsulate it like > this: > > nillable_get_in(root, [:foo, :bar, Access.at(0)]) > > It is concise, backwards compatible, and clear in intent. > > Thoughts? > > On Fri, Feb 7, 2020 at 11:35 PM Greg Vaughn <gvau...@gmail.com> wrote: > I just wanted to follow up and summarize here. I submitted a PR > https://github.com/elixir-lang/elixir/pull/9773 with some more discussion, > but the core point there was that we needed more discussion on the core list > before a PR and it was closed. Nil-safety by default is undesirable in more > Access functions than Access.get. > > I'm exploring this on my own in my own codebase as I rework all the get_in > calls I assumed were nil safe despite using Access.at. I am quite against a > solution that is more verbose to gain mil safety as I use this at the edges > of my system in an anti-corruption-layer. I'd rather see this implemented > once, well, in the standard library than expect thousands of projects to do > it themselves or bring in a 3rd party solutions to achieve it. > > Feel free to discuss some more. > > -Greg > > > On Jan 30, 2020, at 12:02 PM, Allen Madsen <allen.c.mad...@gmail.com> wrote: > > > > I'm in favor of them being nilsafe by default. > > > > Allen Madsen > > http://www.allenmadsen.com > > > > > > On Wed, Jan 29, 2020 at 11:24 AM Tor Bjornrud <bjorn...@gmail.com> wrote: > > I wouldn't mind having opts for something like this. Avoids creating a > > slew of Access functions that then become difficult to sift through. > > > > %{"items" => nil} |> get_in(["items", Access.at(0, nilsafe: true) > > > > On Tuesday, January 28, 2020 at 8:10:04 PM UTC-6, Greg Vaughn wrote: > > Thanks, José. I agree with the need to be consistent. I will look at the > > bigger picture, though, like Manfred I find the addition of "maybe" to be > > awkward, so my preference is to have the existing recommended functions in > > the Access module intended for use with get_in to be consistently nil safe. > > I'm open to more ideas, too. > > > > -Greg Vaughn > > > > > On Jan 28, 2020, at 12:45 PM, José Valim <jose...@dashbit.co> wrote: > > > > > > The proposal is reasonable however it would introduce an inconsistency > > > since the other selectors in Access, such as Access.key, are also not nil > > > safe. So whatever solution we choose needs to be consistent. > > > > > > One possible suggestion is to introduce a "Access.maybe" that composes > > > but composition would have to be back to front: > > > > > > %{"items" => nil} |> get_in(["items", Access.at(0) |> Access.maybe]) > > > > > > Another idea is to introduce maybe_at, maybe_key, maybe_key! and so on. > > > But I am not sure if this is desirable. Thoughts? > > > > > > On Tue, Jan 28, 2020 at 7:33 PM Greg Vaughn <gva...@gmail.com> wrote: > > > I propose that the function returned from Access.at/1 special case nil > > > such that the overall Kernel.get_in/2 call returns nil instead of raising > > > an error. > > > > > > Rationale: > > > I originally blamed this on Kernel.get_in/2 and I'd like to thank Eric > > > Meadows-Jönsson for explaining the underlying reason to me on Slack. > > > > > > I like to think of Kernel.get_in/2 as a nil-safe way of plucking values > > > out of nested data structures, but I learned today that is only partially > > > correct. The nil-safety comes from the underlying Access.get/2 calls. The > > > docs for get_in includes: > > > > > > In case any of the entries in the middle returns nil, nil will be > > > returned as per the Access module: > > > iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}} > > > iex> get_in(users, ["unknown", :age]) > > > nil > > > > > > and I expected use of Access.at/1 in my keys to act similarly, but it > > > doesn't. For example: > > > > > > iex(185)> %{"items" => ["desired_value"]} |> get_in(["items", > > > Access.at(0)]) > > > "desired_value" > > > iex(186)> %{"items" => nil} |> get_in(["items", Access.at(0)]) > > > ** (RuntimeError) Access.at/1 expected a list, got: nil > > > (elixir) lib/access.ex:663: Access.at/4 > > > > > > I propose that the function returned from Access.at/1 special case nil > > > such that the overall get_in/2 call returns nil instead of raising an > > > error. I have not dug into the source yet but I'm happy to work up a PR > > > if there is interest in this change. > > > > > > -Greg Vaughn > > > > > > -- > > > You received this message because you are subscribed to the Google Groups > > > "elixir-lang-core" group. > > > To unsubscribe from this group and stop receiving emails from it, send an > > > email to elixir-l...@googlegroups.com. > > > To view this discussion on the web visit > > > https://groups.google.com/d/msgid/elixir-lang-core/6B6AB775-F3D5-40E5-BFBD-9852FBCBD1D0%40gmail.com. > > > > > > > > > -- > > > You received this message because you are subscribed to the Google Groups > > > "elixir-lang-core" group. > > > To unsubscribe from this group and stop receiving emails from it, send an > > > email to elixir-l...@googlegroups.com. > > > To view this discussion on the web visit > > > https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KZPZ5mpP6SSzhmq3jpuZBYA1irpmOa19UNH2fS_3QKQA%40mail.gmail.com. > > > > > > > > > -- > > You received this message because you are subscribed to the Google Groups > > "elixir-lang-core" group. > > To unsubscribe from this group and stop receiving emails from it, send an > > email to elixir-lang-core+unsubscr...@googlegroups.com. > > To view this discussion on the web visit > > https://groups.google.com/d/msgid/elixir-lang-core/1ae0b9d3-9471-4750-8734-281033e9a1dc%40googlegroups.com. > > > > -- > > You received this message because you are subscribed to the Google Groups > > "elixir-lang-core" group. > > To unsubscribe from this group and stop receiving emails from it, send an > > email to elixir-lang-core+unsubscr...@googlegroups.com. > > To view this discussion on the web visit > > https://groups.google.com/d/msgid/elixir-lang-core/CAK-y3Cu%2BGBO1RWsdAjAHoaukV3w4QJPPdqqNU_miQ_%3Dv5%3DdDeQ%40mail.gmail.com. > > -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elixir-lang-core+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/22988265-AB94-4666-894B-9ECF7B87905D%40gmail.com. > > -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elixir-lang-core+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2B5ovo9YdQHQO2m6i%3DL_SxPKRN4O4fZejH%3DXMXfJWwWkQ%40mail.gmail.com. -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/91D3122B-7112-4303-87DF-3770B8FE5CB9%40gmail.com.