Thanks, that version would work, but agreed - not sure how big of an
improvement that would be over Enum.reduce_while. Trying to think about
this in a more imperative style, it seems that maybe an equivalent of break
is what I'm after? Maybe something close to Ecto's Repo.transaction
semantics?

for foo <- foos do
  case barify(foo) do
    {:ok, bar} -> bar
    {:error, reason} -> break(reason)
  end
end

I think this would have to work similarly to how Ecto's transactions work
with Multis, that is return {:ok, bars} or {:error, reason, data_so_far}.

I have found only one usage of Enum.reduce_while in Elixir's codebase.
Interestingly, the shape of the return value is always the same - a list of
finished tests.
https://github.com/elixir-lang/elixir/blob/main/lib/ex_unit/lib/ex_unit/runner.ex#L340

This seems like a separate problem, but maybe something to keep in mind.

Best,
Stefan


wt., 21 gru 2021 o 00:21 Ben Wilson <benwilson...@gmail.com> napisał(a):

> To revisit the example situation from the original post:
>
> ```
> {sections, _acc} =
> for let {section_counter, lesson_counter} = {1, 1}, section <- sections do
> lesson_counter = if section["reset_lesson_position"], do: 1, else:
> lesson_counter
> {lessons, lesson_counter} = for let lesson_counter, lesson <-
> section["lessons"] do
> {Map.put(lesson, "position", lesson_counter), lesson_counter + 1}
> end
> section =
> section
> |> Map.put("lessons", lessons)
> |> Map.put("position", section_counter)
>
> {section, {section_counter + 1, lesson_counter}}
> end
> ```
>
> I think that's nice! It focuses on inputs and outputs and reduces the
> overall line noise.
>
> On Monday, December 20, 2021 at 5:28:29 PM UTC-5 José Valim wrote:
>
>> Stefan, this would work if we include all extensions:
>>
>> for reduce {status, acc} = {:ok, []}, status == :ok, foo <- foos do
>>   case barify(foo) do
>>     {:ok, bar} -> {:ok, [bar | acc]}
>>
>>     {:error, _reason} = error -> error
>>   end
>> end
>>
>> I am not sure if you find it any better. It is hard to do this with "let"
>> because you don't want to include the element of when it fails.
>>
>> On Mon, Dec 20, 2021 at 9:23 PM Stefan Chrobot <ste...@chrobot.io> wrote:
>>
>>> I went through some of our code and one thing I'd love to see is a way
>>> to replace Enum.reduce_while with the for comprehension. So the code like
>>> this:
>>>
>>> Enum.reduce_while(foos, {:ok, []}, fn foo, {:ok, bars} ->
>>>   case barify(foo) do
>>>     {:ok, bar} -> {:cont, {:ok, [bar | bars]}}
>>>     {:error, _reason} = error -> {:halt, error}
>>>   end
>>> end)
>>>
>>> Would the following even work?
>>>
>>> for reduce(result = {:ok, []}), foo <- foos, {:ok, _} <- result do
>>>   case barify(foo) do
>>>     {:ok, bar} -> {{:ok, [bar | bars]}}
>>>     {:error, _reason} = error -> {error}
>>>   end
>>> end
>>>
>>> Even if it did, it's not doing a great job of communicating the intent
>>> and still potentially requires a Enum.reverse call. The intent here is
>>> "early exit with some value upon some condition or pattern mismatch".
>>>
>>>
>>> Best,
>>> Stefan
>>>
>>> pon., 20 gru 2021 o 21:06 Stefan Chrobot <ste...@chrobot.io> napisał(a):
>>>
>>>> I really like this proposal! For me it strikes the perfect balance
>>>> between terseness and explicitness that I've come to enjoy in Elixir.
>>>>
>>>> My votes:
>>>> - Naming: let over given; just because it's shorter,
>>>> - Do use parents: let "feels" similar to var!.
>>>>
>>>> Best,
>>>> Stefan
>>>>
>>>> pon., 20 gru 2021 o 19:54 José Valim <jose....@dashbit.co> napisał(a):
>>>>
>>>>> Good point. I forgot to mention the :reduce option will be deprecated
>>>>> in the long term.
>>>>>
>>>>> On Mon, Dec 20, 2021 at 7:53 PM 'eksperimental' via elixir-lang-core <
>>>>> elixir-l...@googlegroups.com> wrote:
>>>>>
>>>>>> The proposal is very concise,
>>>>>> the only thing that would be problematic is the use of `reduce` for
>>>>>> two
>>>>>> different things,
>>>>>>
>>>>>> for <<x <- "AbCabCABc">>, x in ?a..?z, reduce: %{} do
>>>>>>   acc -> Map.update(acc, <<x>>, 1, & &1 + 1)
>>>>>> end
>>>>>>
>>>>>> {sum, count} =
>>>>>>   for reduce({sum, count} = {0, 0}), i <- [1, 2, 3] do
>>>>>>     sum = sum + i
>>>>>>     count = count + 1
>>>>>>     {sum, count}
>>>>>>   end
>>>>>>
>>>>>> It would lead to misunderstanding as it may not be clear which one we
>>>>>> are talking about when we say "use for reduce"
>>>>>>
>>>>>>
>>>>>>  On Mon, 20 Dec 2021 19:11:54 +0100
>>>>>> José Valim <jose....@dashbit.co> wrote:
>>>>>>
>>>>>> > Hi everyone,
>>>>>> >
>>>>>> > This is the second proposal for-let. You can find it in a gist:
>>>>>> > https://gist.github.com/josevalim/fe6b0bcc728539a5adf9b2821bd4a0f5
>>>>>> >
>>>>>> > Please use the mailing list for comments and further discussion.
>>>>>> > Thanks for all the feedback so far!
>>>>>> >
>>>>>>
>>>>>> --
>>>>>> 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/61c0d119.1c69fb81.af520.c181SMTPIN_ADDED_MISSING%40gmr-mx.google.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 elixir-lang-co...@googlegroups.com.
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4LOyoAmXULJQo%2BYX4eFVJZJAoYtKHytoHujCS_kJ6AEuA%40mail.gmail.com
>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4LOyoAmXULJQo%2BYX4eFVJZJAoYtKHytoHujCS_kJ6AEuA%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/CACzMe7aXBL1jNM_aWmJJzYOjrK%3Dtf-4%2BLPLJLpccu_G4zr0cAg%40mail.gmail.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/CACzMe7aXBL1jNM_aWmJJzYOjrK%3Dtf-4%2BLPLJLpccu_G4zr0cAg%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/c1fea9e2-f47c-4236-812a-431bc7d76d62n%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/c1fea9e2-f47c-4236-812a-431bc7d76d62n%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/CACzMe7YgonBdGtJaK5Y_nHKdibWOX0TK0zfKy6029TeuZeB4Qw%40mail.gmail.com.

Reply via email to