Withdrawn. José convinced me. -bt
On Wed, Dec 9, 2020 at 3:10 PM eksperimental <[email protected]> wrote: > Looking back, I think having acc as the first argument would be have a > better choice. But we have other functions named after "fold" such as > List.foldl/3, List.foldr/3, Inspect.Algebra.fold_doc/2 that take a > function in the same format as Enum.reduce/3. So having some > fold functions that take a function in the (current_acc, element -> > updated_acc) format and others in the (element, current_acc -> > updated_acc) would be hard to remember which one is which. I guess this > proposal should consider a different name for the new function. > > On Wed, 9 Dec 2020 09:40:35 -0500 > Bruce Tate <[email protected]> wrote: > > > This is a long post, and I think it might not be a popular one. > > Still, I think it has an important punchline, so bear with me. > > > > Proposal: Add Enum.fold/2 and Enum.fold/3 (and the Stream > > counterparts). These both work like Enum.reduce, but flip the > > arguments in the reducer function. > > > > As I teach and code Elixir, I have four steps for most students. > > First, we build common vocabulary and language constructs of Elixir. > > Next, we think in terms of a common pattern I call > > constructor-reducer-converter. (More in a sec.) Then, we apply that > > pattern in higher level constructs like LiveView and OTP. Finally, we > > build projects and let students code these patterns for themselves. > > In a phrase, *everything is reduce*. I want to focus on that second > > step. > > > > I am thinking and teaching more about one common pattern. At its core, > > Elixir modules have functions around a common type T that either > > produce, transform, or consume T. I call these functions > > constructors, reducers, and converters. They all interact with type T. > > > > Think of them in this way: > > > > constructor(inputs) |> reducer(...) |> reducer(...) ... |> converter > > > > This is the way the data-centric modules in Elixir are built today. In > > Designing Elixir Systems with OTP speak, they are the *core* modules, > > and I believe many Elixir developers build code this way, even if we > > don't vocalize it in this way. > > > > Building code like this puts us in conflict in one important way: > > > > 1. Elixir modules are generally organized around data of a common type > > (let's say T) > > 2. Named functions in a module have T as the first argument. > > 3. Pipes rely on T as a first argument. > > 4. In Enum.reduce, T is the accumulator, and it's the second argument > > of the reducer. > > > > 3 and 4 are in conflict! The accumulator plays the role of T in the > > reducer: > > > > reducer(any(), T) :: T > > > > That's backwards, and it won't pipe. > > > > If we have this: > > > > 10 |> subtract(4) |> subtract(3) > > > > and we want to express that code over a list that's arbitrarily long, > > we we must do this: > > > > Enum.reduce([4, 3, ...], 10, fn x, acc -> subtract(acc, x) end) > > > > to flip the two arguments to the correct place. > > > > But we can't do so. I know the Elixir way is to generally put up with > > a little ceremony for the common good of a tighter standard library, > > most of the time, but I don't think this problem applies. I think > > that Elixir *wants* this function: > > > > Enum.fold([4, 3], 10, &subtract2) > > > > To me the cost is high: > > > > 1. We must add a function to Enum, a central Elixir function > > 2. The function does almost the same thing as an existing function. > > > > To me at least the benefit is higher: > > > > Enum.fold encourages us to write better code in three ways: > > > > A, Enum.fold encourages us to write code with T first, the Elixir way. > > > > B, Enum.fold encourages named functions rather than anonymous > > functions which leads to more opportunities to name concepts without > > comments, always a good thing. > > > > C. This strategy has a profound impact on tests of reducers, as we can > > simply pipe them and check the results. > > > > What do you think? > > -bt > > > > -- > 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/5fd12f36.1c69fb81.6e0da.1dc6SMTPIN_ADDED_MISSING%40gmr-mx.google.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-5ou4GREnD%3DQNPLrUr76Xq-ppnBf5Od1VtTK850_%2BfCug%40mail.gmail.com.
