In my opinion, these are exactly the kinds of functions we should be adding. They address common scenarios that make it easier on beginners, and encourages the practices we want. +1from me.
-bt On Wed, Dec 30, 2020 at 11:06 AM Greg Vaughn <[email protected]> wrote: > I really like the idea of a convenience function in the Keyword module. > One idea that comes to mind: > > Keyword.limit_keys!([parentheses: 10], [:parenthesis]) > raises or returns 1st param unchanged. > > -Greg > > > On Dec 30, 2020, at 4:53 AM, José Valim <[email protected]> wrote: > > > > The issue is that for take!, I can see two semantics: > > > > 1. The map/keyword must have all of the given keys > > 2. The map/keyword must have at most the given keys > > > > And I think 1) makes more sense intuitively. :( > > > > On Wed, Dec 30, 2020 at 11:48 AM Wojtek Mach <[email protected]> > wrote: > > Fair enough, agreed about decoupling the problem. In that case I’d still > offer > > Keyword.take!/2 that works like this: > > > > iex> Keyword.take!([a: 1], [:a, :b]) > > [a: 1] > > > > iex> Keyword.take!([c: 1], [:a, :b]) > > ** (ArgumentError) > > > > I think take/2 and take!/2 matches struct/2 and struct!/2. > > > >> On 30 Dec 2020, at 11:30, José Valim <[email protected]> wrote: > >> > >> Wojtek, I originally thought about Map.merge!, where the second > argument must be a subset of the first. This way we can check keys and > provide default values: > >> > >> Keyword.merge!([parenthesis: 10], opts) > >> > >> However, when I tried using this in practice, I realized that default > arguments are not always straight-forward to compute. For example, you may > want to compute them lazily. You could argue we could set them to nil in > said cases, but then we'd mix the absence of a key with nil value, which > may not be desired. > >> > >> Therefore, I concluded that it is probably best to keep those problems > separated and validate only the keys. I agree with Andrea that this is > small but the benefit I see having it in core is to promote more folks to > use it. Both Python and Ruby provide at the syntax-level a convenience that > checks only the given keys are expected. So, when it comes to options, both > of these languages are allowing us to write assertive code more elegantly > than Elixir. > >> > >> > >> On Wed, Dec 30, 2020 at 10:10 AM Wojtek Mach <[email protected]> > wrote: > >> I think this would be a great addition to the core. > >> > >> While there are libraries in this space, as silly as this may seem, > solving > >> this key typo problem seems like solving the 60%-80% case (not to take > away > >> anything from those libraries!) > >> > >> How about a Keyword.take!/2? > >> > >> iex> Keyword.take!([a: 1], [:a, :b]) > >> [a: 1] > >> > >> iex> Keyword.take!([c: 1], [:a, :b]) > >> ** (ArgumentError) unknown key :c in [c: 1] > >> > >> There are however two problems with it: > >> > >> 1. would people expect that `Keyword.take!([a: 1], [:a, :b])` should > fail > >> because `:b` is not in the input? > >> > >> Maybe the 2nd argument accepts defaults? (I know it probably starts > doing > >> too much...) > >> > >> iex> Keyword.take!([a: 1], [:a, :b]) > >> [a: 1, b: nil] > >> > >> iex> Keyword.take!([a: 1], [:a, b: 2]) > >> [a: 1, b: 2] > >> > >> In fact this could have the following semantics: if there's no > default, it's > >> a required key: > >> > >> iex> Keyword.take!([], [:a, b: 2]) > >> ** (ArgumentError) missing required key :a > >> > >> What's nice is you can later use `Keyword.fetch!/2` that will save > you from > >> typos. > >> > >> But that being said, If the 2nd argument accepts a keyword, then it > >> probably shouldn't be called `take!/2` as it no longer matches > `take/2`. > >> > >> 2. If you do: `opts = Keyword.take!(..., ...)` and later > `opts[:my_key]` you > >> still have an opportunity for a typo and you can't necessarily use > >> `Keyword.fetch!/2` because optional keys might not be there. > >> > >> As Devon mentioned, structs are a really cool solution because they > provide > >> rigidity, defaults, and the assertive map access syntax with ".". > Creating a > >> struct for every function that accepts options feels like a bit much > though. > >> > >> Taking everything above into consideration, perhaps there's: > >> > >> iex> Map.something_something!([], [:name, timeout: 5000]) > >> ** (ArgumentError) missing required key :name > >> > >> iex> opts = Map.something_something!([name: Foo], [:name, timeout: > 5000]) > >> iex> opts.timeout > >> 5000 > >> > >> and I feel like it's still relatively small addition but it's closer to > the > >> "80% solution". No idea how to name this thing though! > >> > >> > >> > >>> On 30 Dec 2020, at 09:36, Devon Estes <[email protected]> wrote: > >>> > >>> Typos are extremely hard to prevent in dynamic data structures since > validations need to be implemented at the point of use instead of at the > point of creation/definition of the structure. What would stop the > developer from writing the typo in their validation, as José did in his > example? > >>> > >>> It seems to me like if the goal is to prevent typos then a struct > would be the way to go. > >>> > >>> Kurtis Rainbolt-Greene <[email protected]> schrieb am Mi. > 30. Dez. 2020 um 09:29: > >>> Yes, but think of the valuable hours saved and the amount of code that > won't have to be written. > >>> > >>> I mean even Valim's own example again has the typo. > >>> > >>> On Tue, Dec 29, 2020 at 11:58 PM Andrea Leopardi < > [email protected]> wrote: > >>> Considering how straightforward the code you showed is, and that for > more complex scenarios we have libraries like nimble_options, I might be > slightly hesitant to add this to core. > >>> > >>> Andrea > >>> > >>> On Wed, 30 Dec 2020 at 08:53, José Valim <[email protected]> > wrote: > >>> Hi everyone, > >>> > >>> I am working on a new project and yesterday I spent a couple hours on > a bug due to a in a keyword list. In a nutshell, I was supposed to pass > parenthesis: 10 as keywords to a function but I passed parentheses: 10. > >>> > >>> I have fixed the issue by adding the following code: > >>> > >>> for {k, _} <- keyword, k not in [:parentheses, :other_options], > do: raise "unknown key #{inspect(k)} in #{inspect(keyword)}" > >>> > >>> The code is super straight-forward but I am wondering if we should add > it to Elixir to promote said validation. What do you think? Any suggestions > on where it should be defined and with which name? > >>> > >>> Thank you! > >>> > >>> > >>> -- > >>> 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 [email protected]. > >>> To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J8_RG5eeCZSw_c75Q4y19YFt-ipdnTAEa1cE2GnvwjrQ%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 [email protected]. > >>> To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAM9Rf%2BJPu8tF2VzNB4beDqO9jc%2BF-SDE6u%3D724EZm9271jY2ug%40mail.gmail.com > . > >>> > >>> > >>> -- > >>> Kurtis Rainbolt-Greene, > >>> Software Developer & Founder of Difference Engineers > >>> 202-643-2263 > >>> > >>> -- > >>> 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 [email protected]. > >>> To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAMhJPGiKh3uOaY2UNDFYu9x64n-mM7Sqf7iHU09QeAmfOY0mwQ%40mail.gmail.com > . > >>> -- > >>> > >>> _________________ > >>> Devon Estes > >>> +49 176 2356 4717 > >>> www.devonestes.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 [email protected]. > >>> To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAGowJcg_DWYAQsys5f6Ad1nYket8be1Lsrmui8Uh%3DzEAKzWzTQ%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 [email protected]. > >> To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/5E7686D9-1DC6-4830-8C32-7FCAFFE6E706%40wojtekmach.pl > . > >> > >> -- > >> 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 [email protected]. > >> To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2B9YG1YwoK9JGAitzOzikOeo4dXCHyvu%3DjAU6SN1HRocw%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 [email protected]. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/2A76D025-BF9B-45E1-B268-DD23753FEC6C%40wojtekmach.pl > . > > > > -- > > 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 [email protected]. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4Jx0-0xU76qaury3k5P8WuKjNRj8xUKj1Cz8a0YyuX%2BMA%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 [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/F639C82D-9AB5-4CBC-991C-EC895C8037E3%40gmail.com > . > -- Regards, Bruce Tate CEO <https://bowtie.mailbutler.io/tracking/hit/f8218219-d2a8-4de4-9fef-1cdde6e723f6/c7c97460-016e-45fb-a4ab-0a70318c7b97> Groxio, LLC. 512.799.9366 [email protected] grox.io -- 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAFXvW-6t3fC2hWQB_MWe%3DDiGvFs5hpJfPK8LRDtHUo%2Bv6uSKrA%40mail.gmail.com.
