Hi Marten, Thanks for the feedback!
The only reason I picked "then" is exactly because, if we ever introduce something akin to monads, I wouldn't pick "then" because I don't think it is clear enough on its monadic value. Also note that: 1. "andThen" in Scala is function composition and not bind. bind is flatMap (which I personally prefer) 2. "andThen" in Elm is indeed bind but it is not polymorphic, so you have Task.then, Maybe.then, etc. Therefore, even if we decide to go with "then" in the future, there is no naming conflict, unless we choose a polymorphic monad implementation. In fact, Kernel.then could then be used as an introduction to other monadic modules. So overall I think we are clear. This will be a bad choice only if all of the below are true: 1. We introduce monads 2. We pick "then" as the name for bind 3. Monads are polymorphic so we are accessing them via an imported "then" instead of qualified per module Happy holidays! On Tue, Dec 29, 2020 at 12:32 PM w...@resilia.nl <w...@resilia.nl> wrote: > 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 > <https://groups.google.com/d/msgid/elixir-lang-core/4375daa4-9e65-4f4c-95a1-2d9147718d48n%40googlegroups.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/CAGnRm4Jo-z4oGUimj0GZTL1HD8sFi91aWNTSvkLLkAiB63egpg%40mail.gmail.com.