A small idea It might be interesting to look at this as an extension of existing Kernel.destructure/2: https://hexdocs.pm/elixir/1.12/Kernel.html#destructure/2
Right now it works like this destructure([x, y, z], [1, 2, 3, 4, 5]) # in other words, destructure(form_with_bindings, data) But if we provide another function, say destructure(data, form, new_form, default \\ nil), with `new_form` specifying which data it should return based on binds from `form`, we can easily use it in pipes like this: data |> ... |> destructure({:ok, result}, result) |> ... |> destructure([a, b, c], %{a => 42 + b * c}) |> ... On Wednesday, 14 December 2022 at 2:36:48 am UTC+1 matt.fa...@covermymeds.com wrote: > Thank you for the useful feedback! Let me try addressing your excellent > points in turn: > > > > 1. While `then/2` and `case/2` are somewhat suitable, they are > verbose, especially in the case of the non-raising alternative. The > additional typing involved for the anonymous function distracts the reader > from the pattern matching, which is the crux of the matter. > 2. With my implementation, the macro returns an empty string: assert > “” == “$” |> pattern_filter(“$” <> money) > 3. The `with/1` pipeline is verbose and lacks the visual flow of |> > 4. The way I wrote the macro stipulates that there is only one > non-underscored variable per pattern. Changing the examples you provided > to > `{a, _*b}` and `{*_a, b, _a}` would work just as well and remove > ambiguity as to the return > 1. So {1,2,1} |> pattern_filter({_a, b, _a}) is more concise and > just as clear, imo > 2. This does raise a warning, though I’m not sure why the warning > is issued for a pattern like this. It just kind of (politely) tells me > to > remove the underscores, though the code works as intended. > > > > > > > > > > > > *From: *<elixir-l...@googlegroups.com> on behalf of Sabiwara Yukichi < > sabi...@gmail.com> > *Reply-To: *"elixir-l...@googlegroups.com" <elixir-l...@googlegroups.com> > *Date: *Tuesday, December 13, 2022 at 6:55 PM > *To: *"elixir-l...@googlegroups.com" <elixir-l...@googlegroups.com> > *Subject: *[EXTERNAL] Re: [elixir-core:11213] [proposal] Use patterns to > filter data (good for pipes) > > > > This email came from a source outside of CoverMyMeds. Use caution when > clicking on links or replying with confidential information. > ------------------------------ > > This is an interesting idea, but maybe `then/2` (or case/2 if you're fine > piping in it) could already cover these cases quite well (equivalent to > your pattern_filter! function): > > > > "$3.45" |> then(fn "$" <> money -> money end) |> String.to_float() > > "$3.45" |> case do "$" <> money -> money end |> String.to_float() > > > > The non-raising alternative might be slightly more verbose because you > need a second clause. But most of the time (like your money example), the > next step of the pipe might fail on nil anyway. Or maybe a with/1 pipeline > might work better than the pipe operator if you want a succession of > happy-path matches? > > > > If we move forward, it might be better to explicitly declare the returned > expression, not just infer it from dangling variables: it isn't obvious > what should `{a, b}` or `{a, b, a}` return. Something like: > > > > {1, 2, 1} |> pattern_filter(b <- {a, b, a}) > > > > Le mer. 14 déc. 2022 à 05:50, 'Matt Farabaugh' via elixir-lang-core < > elixir-l...@googlegroups.com> a écrit : > > All, > > > > I wrote a macro which allows for using a pattern to essentially extract a > value from a data structure: > > > > > @doc """ > Filter a value out of data using a pattern with one variable. Returns a > default value > if no match. Raises if pattern contains no variables or more than one > variable. > > ## Examples > > iex> "$3.45" |> PatternHelpers.pattern_filter("$" <> money) |> > String.to_float() > 3.45 > > iex> {1,2,3} |> PatternHelpers.pattern_filter({1,_,a}) > 3 > > iex> %{a: 1, b: 2} |> PatternHelpers.pattern_filter(%{a: 9, b: b}) > nil > > iex> %{a: 1, b: 2} |> PatternHelpers.pattern_filter(%{a: 9, b: b}, "???") > "???" > """ > > > > And an unsafe version: > > > > @doc """ > See `pattern_filter/3`. Raises if no match. > > ## Examples > > iex> {1,2,3} |> PatternHelpers.pattern_filter!({9,_,b}) > ** (MatchError) no match of right hand side value: {1, 2, 3} > """ > > > > This is my first proposal. Please let me know if this idea is worth some > attention, and how I might better do my part to present it. I have code > obviously but I'm not sure this is the place for it. > > > > Thanks, > > Matt F > > -- > 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-co...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/4b65083e-6c36-4519-a0ed-fa2da8b61a9bn%40googlegroups.com > > <https://urldefense.com/v3/__https:/groups.google.com/d/msgid/elixir-lang-core/4b65083e-6c36-4519-a0ed-fa2da8b61a9bn*40googlegroups.com?utm_medium=email&utm_source=footer__;JQ!!LBRzLL-rxcoG!soAu7_j204hUseqlxMsemQMOhOz0yO8WygSZdV2t7WGq5iDQfDh-prkOc8PkTmo4vz08vKeE_ZmAZ19k2vMrPomauA$> > . > > -- > 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-co...@googlegroups.com. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CANnyohYy8hRvu2WD%2BMUEzWS2SxoA8eYk9PETOe8jGxr2tiuW%2BA%40mail.gmail.com > > <https://urldefense.com/v3/__https:/groups.google.com/d/msgid/elixir-lang-core/CANnyohYy8hRvu2WD*2BMUEzWS2SxoA8eYk9PETOe8jGxr2tiuW*2BA*40mail.gmail.com?utm_medium=email&utm_source=footer__;JSUl!!LBRzLL-rxcoG!soAu7_j204hUseqlxMsemQMOhOz0yO8WygSZdV2t7WGq5iDQfDh-prkOc8PkTmo4vz08vKeE_ZmAZ19k2vMQT4CMDA$> > . > > This electronic transmission is confidential and intended solely for the > addressee(s). If you are not an intended addressee, do not disclose, copy > or take any other action in reliance on this transmission. If you have > received this transmission in error, please delete it from your system and > notify CoverMyMeds LLC at pri...@covermymeds.com. 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 elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/4cdeeb01-0446-4385-bea5-062476cc76c2n%40googlegroups.com.