1. tap: I think adding tap will be very useful. I often am doing something like
``` ast = quote do ... end IO.puts(Macro.to_string(ast) ast ``` when debugging macros. Being able to change this to ``` quote do ... end |> tap(&IO.puts(Macro.to_string(&1)) ``` will be very welcome. :-) 2. then: What José is referring to (when talking about `then` in relation to other languages where it is also used for e.g. promises) is the monadic 'bind' operation. You might also know it as `>>=` as well as `andThen`: - `>>=` is the (non-descriptive) symbolic name that is used in Haskell, PureScript, and F# as well as many papers. - `bind` is the name given to above operation. It is also a frequently-used name whenever an operator is not used. In fact, `bind` is used in the Elixir ecosystem right now. One example that comes to mind is `StreamData`. There are probably others. - `andThen` sees usage in Scala, Elm and as already mentioned by José in many other contexts whether they deal with only promises, only parsers, only nondeterminism, etc... or monads in general. Even if it is more verbose, I think the name `andThen` is more descriptive than plain `then`. Therefore I prefer `andThen`. But rather I'd not add it at all: This proposed function will only be specialized to the "identity monad". The bind operation is the place where the unwrapping of the monadic value ought to happen. The identity monad is the one case where there is nothing to unwrap. `then/2` as described is a function that does nothing over using the function directly, except for "circumventing" the parsing precedence issue of `&` vs `|>` (if you need a refresher, find prior discussion about allowing anonymous functions and captures in pipes here <https://github.com/elixir-lang/elixir/issues/10154>). `then/2` only exists for improved syntax, not for improved semantics. The fact that we are specializing it for this single syntactic purpose makes me consider that maybe we'd be better off choosing a different name that does not have this pre-existing meaning attached. Even if you're unfamiliar with monads or algebraic datatypes in general, you'll be able to understand the problem of restricting a general operation to one specific case. It's a bit like saying "Let's add a `Kernel.sum/1` that sums (only) lists of integers." It 'works' but what about lists of floats? sets of integers? lists of decimals? etc. There is a lot of missed potential. There is a high possibility that a decision like this cannot be extended or altered later on in a backwards-compatible way. There is a high likelihood of people trying to use it in contexts where it cannot be used and being confused by it or introducing bugs. So I'd seriously consider using a different naming scheme for `then`. I'd prefer a simpler name with less of a pre-existing meaning. Possibly just `fun/2`. Happy holidays! :-) ~Marten/Qqwy On Tuesday, December 29, 2020 at 10:47:17 AM UTC+1 José Valim wrote: > I propose we simply add two functions to Kernel: tap and then. > > 1. tap receives an anonymous function, invokes it, and returns the > argument. It can be found in Ruby and .NET Rx. > > 2. then receives an anonymous function, invokes it, and returns the result > of the anonymous function. It will be how we can pipe to anonymous > functions in Elixir. It is named andThen in Scala and known as then in many > promise libraries across ecosystems. > > I think this can improve the piping experience considerably while keeping > things functional. > > On Tue, Dec 29, 2020 at 4:20 AM Zach Daniel <zachary....@gmail.com> wrote: > >> That takes it a bit too far for my taste. That part can easily be done by >> passing an anonymous function and calling a series of functions. >> >> On Mon, Dec 28, 2020 at 9:55 PM Kevin Johnson <johnson7...@gmail.com> >> wrote: >> >>> I would prefer to introduce a general approach to this, such that: >>> >>> How general do you want it to be? >>> Is this to cater solely for conveniently inlining side-effects; e.g. >>> write to log, network, console or are there other use-cases that you >>> envision? >>> Do you envision inlining multiple side-effects: >>> `|> tap(&Map.keys/1, [&IO.inspect/1, &KafkaEx.produce("foo", 0, >>> &Poison.encode!(&1)), ...])` to facilitate some fan-out strategy with >>> perhaps some desired options? >>> >>> -- >>> 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/CAAkfbUr9Ud1iKo0X1bCu1tcL5V1M-Z0um6-8JyFA0kOeh7fUmA%40mail.gmail.com >>> >>> <https://groups.google.com/d/msgid/elixir-lang-core/CAAkfbUr9Ud1iKo0X1bCu1tcL5V1M-Z0um6-8JyFA0kOeh7fUmA%40mail.gmail.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- >> 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/CAK-yb0CYHpkZ5-qhM3CMx-VcUnkk16SC55_hOK-b%3DSPg%3DFzqXA%40mail.gmail.com >> >> <https://groups.google.com/d/msgid/elixir-lang-core/CAK-yb0CYHpkZ5-qhM3CMx-VcUnkk16SC55_hOK-b%3DSPg%3DFzqXA%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> > -- 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/4375daa4-9e65-4f4c-95a1-2d9147718d48n%40googlegroups.com.