Apologies, I re-read my first reply to you and it was definitely not clear
I was taking about both approaches.

On Fri, Dec 17, 2021 at 19:45 José Valim <jose.va...@dashbit.co> wrote:

> That’s what I meant. The reduce solution requires the reverse. The state
> proposal is very close to the Enum.map_reduce/3 solution, as it keeps all
> of its noise in passing the accumulator, matching on it, and returning it.
>
> I am sure it is clear for an Elixir developer but so is Enum.map_reduce/3.
> Can we find a point midway? Maybe yes, maybe no. :)
>
> PS: And, although we got used with for+:reduce, we have to admit that the
> fact the accumulator is matched in a clause inside do-end is a specific
> behavior to for that we partly accept because we got used to it!
>
> On Fri, Dec 17, 2021 at 19:19 Zach Daniel <zachary.s.dan...@gmail.com>
> wrote:
>
>> The first approach I described was just me confirming my understanding of
>> a corollary of the desired behavior that we can do now. The original
>> problem stated using the method I showed in my second example would look
>> like this, which seems pretty clean to me.
>>
>> ```
>> section_counter = 1
>> lesson_counter = 1
>>
>> {sections, _} =
>>   for section <- sections,
>>       state: %{section_counter: section_counter, lesson_counter:
>> lesson_counter} do
>>     %{lesson_counter: lesson_counter, section_counter: section_counter} ->
>>       lesson_counter = if section["reset_lesson_position"], do: 1, else:
>> lesson_counter
>>
>>       {lessons, lesson_counter} =
>>         for lesson <- section["lessons"], state: lesson_counter do
>>           lesson_counter ->
>>             lesson = Map.put(lesson, "position", lesson_counter)
>>             {lesson, lesson_counter + 1}
>>         end
>>
>>       section =
>>         section
>>         |> Map.put("lessons", lessons)
>>         |> Map.put("position", section_counter)
>>
>>       {section, %{section_counter: section_counter + 1, lesson_counter:
>> lesson_counter}}
>>   end
>> ```
>> Although I did originally forget to include the fact that if `state` is
>> specified then not only do you match on it and return a tuple, but that the
>> comprehension would return a tuple as well.
>>
>> Sent via Superhuman <https://sprh.mn/?vip=zachary.s.dan...@gmail.com>
>>
>>
>> On Fri, Dec 17, 2021 at 1:04 PM, José Valim <jose.va...@dashbit.co>
>> wrote:
>>
>>> Hi Zach,
>>>
>>> I recommend trying out your approach on the original problem. You will
>>> see that you will need to accumulate elements, add Enum.reverse/1, etc. All
>>> which will make the solution noisier.
>>>
>>> On Fri, Dec 17, 2021 at 6:59 PM Zach Daniel <zachary.s.dan...@gmail.com>
>>> wrote:
>>>
>>>> I may not fully be understanding what we're looking for here, but it
>>>> seems like this would effectively be the equivalent of:
>>>>
>>>> ```
>>>> result =
>>>> for foo ← [1, 2, 3], reduce: %{acc: [], counter: 0} do
>>>>   %{acc: acc, counter: counter} ->
>>>>     new_acc = some_calc(acc)
>>>>     %{acc: new_acc, counter: counter + 1}
>>>> end
>>>>
>>>> actual_result = result.acc
>>>> ```
>>>>
>>>> I'm wondering if we could just introduce an additional `state` that you
>>>> match on, and return as a tuple from the for loop body? I think this is
>>>> similar to what the original proposal wanted, but it involves only knowing
>>>> that if you use the `state` option, you need to return a tuple of the for
>>>> loop result and the new state. And it looks similar to a genserver in that
>>>> regard, which makes it feel reasonably conventional.
>>>>
>>>> ```
>>>> result =
>>>>   for foo ← [1, 2, 3], reduce: [], state: %{counter: 0} do
>>>>     acc, state →
>>>>      {some_calc(acc, state.counter), %{state | counter: state.counter +
>>>> 1}}
>>>>   end
>>>> ```
>>>>
>>>>
>>>> Sent via Superhuman <https://sprh.mn/?vip=zachary.s.dan...@gmail.com>
>>>>
>>>>
>>>> On Fri, Dec 17, 2021 at 10:35 AM, João Pedro Evangelista <
>>>> evangelistajo...@gmail.com> wrote:
>>>>
>>>>> *> In fact, making special-semantics different syntactically to be
>>>>> more googleable *
>>>>>
>>>>> Also more easily scannable while reading the code, we would know that
>>>>> this variable has more meaning among the other ones
>>>>> On Friday, December 17, 2021 at 9:32:18 AM UTC-3 christ...@gmail.com
>>>>> wrote:
>>>>>
>>>>>> *> I did consider introducing (precisely) $ for variables but my
>>>>>> concern is that, by introducing special syntax, I believe most would 
>>>>>> expect
>>>>>> it to be fully mutable, so you can modify it from any scope.*
>>>>>>
>>>>>> I am not sure if I can envision a way to allow imperative-ish
>>>>>> variables without introducing special semantics. So I feel like 
>>>>>> supporting
>>>>>> the new semantics with special syntax would allow us to set correct
>>>>>> expectations about its scope and mutability when introducing/documenting 
>>>>>> it!
>>>>>>
>>>>>> In fact, making special-semantics different syntactically to be more
>>>>>> googleable is a perk over plain variables in my mind. For example,
>>>>>> searching *"ruby double at"* (a comparatively oblique ruby language
>>>>>> identifier feature, *@@class_variables*), returns an appropriate top
>>>>>> result
>>>>>> <https://stackoverflow.com/questions/5890118/what-does-variable-mean-in-ruby>
>>>>>> (from an incognito browser session, no less)! So maybe an *"elixir
>>>>>> dollar variable" * google search is a reasonable standard to hold
>>>>>> ourselves to.
>>>>>>
>>>>>> On Friday, December 17, 2021 at 5:40:14 AM UTC-5 sabi...@gmail.com
>>>>>> wrote:
>>>>>>
>>>>>>> Indeed this doesn't address the issue of the level of nesting, and
>>>>>>> is confusing in this case.
>>>>>>>
>>>>>>> The new syntax could maybe include the level of nesting information
>>>>>>> somehow, e,g. `* $section_counter*` in the parent loop, `*
>>>>>>> $$section_counter*` in the child loop...?
>>>>>>> Or *$1.section_counter = 1 *(parent),* $2.section_counter = 1 *
>>>>>>> (child)? (slightly inspired by &1)
>>>>>>> *.*
>>>>>>>
>>>>>>> Another way to deal with this inconsistency could be to forbid
>>>>>>> nested comprehension with variables, and require to extract as a new
>>>>>>> function (in the same way the & cannot be nested and require to use fn).
>>>>>>> Most examples would probably be easier to understand this way
>>>>>>> anyway, but this might limit the power of the feature.
>>>>>>>
>>>>>>> Or maybe just having the compiler raising an error if trying to
>>>>>>> re-assign within a nested block, with a helpful beginner-friendly 
>>>>>>> message,
>>>>>>> could be enough to clear this confusion?
>>>>>>> I think this is not so much harder to figure than the fact than a
>>>>>>> re-assignment within an *if* doesn't work as in imperative
>>>>>>> languages.
>>>>>>>
>>>>>>> By looking at the examples here, I feel that the last one might be
>>>>>>> the most elegant of these 3 ideas:
>>>>>>> https://gist.github.com/sabiwara/97c480c2076666ba9b98cf7a142a5a0f
>>>>>>>
>>>>>>>
>>>>>>> Le ven. 17 déc. 2021 à 16:14, José Valim <jose....@dashbit.co> a
>>>>>>> écrit :
>>>>>>>
>>>>>>>> *Re: for section <- sections, $section_counter = 1, $lesson_counter
>>>>>>>> = 1 do*
>>>>>>>>
>>>>>>>> I did consider introducing (precisely) $ for variables but my
>>>>>>>> concern is that, by introducing special syntax, I believe most would 
>>>>>>>> expect
>>>>>>>> it to be fully mutable, so you can modify it from any scope. That's
>>>>>>>> why I decided to go with plain variables, because they already have a
>>>>>>>> limited scope in Elixir and clear rules (but at the same time I agree 
>>>>>>>> that
>>>>>>>> adding :let would make those clear rules precisely more confusing!).
>>>>>>>>
>>>>>>>> On Fri, Dec 17, 2021 at 7:01 AM Christopher Keele <
>>>>>>>> christ...@gmail.com> wrote:
>>>>>>>>
>>>>>>>>> I love the thought put into this proposal, and really like the
>>>>>>>>> problem it is tackling! I am looking forward to the next proposal and 
>>>>>>>>> will
>>>>>>>>> try to get to my inbox earlier for it.
>>>>>>>>>
>>>>>>>>> *Proposal Feedback*
>>>>>>>>>
>>>>>>>>> I mostly second the impressions voiced here, but *really* want to
>>>>>>>>> call attention to the criticism:
>>>>>>>>>
>>>>>>>>> *> this breaks refactoring for the inner contents of `for`*
>>>>>>>>>
>>>>>>>>> This is the real true deal-breaker for me. Referential
>>>>>>>>> transparency is a huge part of my mental model of Elixir and the key 
>>>>>>>>> reason
>>>>>>>>> why it is such a joy to maintain code in. I am not sure if it is 
>>>>>>>>> possible
>>>>>>>>> to introduce an imperative-loop construct that *doesn't* violate
>>>>>>>>> this property, so I may have to get over that. I do remember how 
>>>>>>>>> painful it
>>>>>>>>> was to remove assignment-inside-ifs, though.
>>>>>>>>>
>>>>>>>>> *Replies*
>>>>>>>>>
>>>>>>>>> *Re: **for section <- sections, $section_counter = 1,
>>>>>>>>> $lesson_counter = 1 do*
>>>>>>>>>
>>>>>>>>> *> Maybe a possibility could be to distinguish comprehension
>>>>>>>>> variables, for example by prefixing them in the same way as module
>>>>>>>>> attributes are prefixed with `@`.*
>>>>>>>>>
>>>>>>>>> This does elegantly solve my refactoring concern; in that
>>>>>>>>> "imperative" comprehension variables copied out of the comprehension 
>>>>>>>>> could
>>>>>>>>> immediately raise a syntax error, as would moving them into a 
>>>>>>>>> different
>>>>>>>>> comprehension that does not have them declared as imperative in the
>>>>>>>>> comprehension head. The compiler would also have to enforce never 
>>>>>>>>> letting
>>>>>>>>> you use the same name with an imperative variables as with a normal 
>>>>>>>>> one, to
>>>>>>>>> completely eliminate edge cases. I think this solution even works for
>>>>>>>>> nested comprehensions, though I still am not sure how *that*
>>>>>>>>> would work with the existing proposal.
>>>>>>>>>
>>>>>>>>> *> We could maybe even remove the `let` keyword altogether?*
>>>>>>>>>
>>>>>>>>> *That * makes me really like syntax. We are not exactly running
>>>>>>>>> short on propositions but it nice to keep that overhead low. Also, 
>>>>>>>>> the only
>>>>>>>>> other existing identifier syntax (module attributes) use a 
>>>>>>>>> prefix/sigil
>>>>>>>>> approach as well, and this feels in the same category to me: we are
>>>>>>>>> introducing a different type of identifier with different scoping 
>>>>>>>>> rules
>>>>>>>>> (even though what happens at compile time to it is wildly different).
>>>>>>>>>
>>>>>>>>> *Re: **overloading the **<- operator*
>>>>>>>>>
>>>>>>>>> *> My concern about this is that `<-` in for means extracting
>>>>>>>>> something from the collection, so giving it another meaning inside an
>>>>>>>>> option can be quite confusing.*
>>>>>>>>>
>>>>>>>>> *> If I'm not mistaken it actually means pulling the next item
>>>>>>>>> from an enumerable.*
>>>>>>>>>
>>>>>>>>> FWIW I've been writing Elixir for years and I still forget when I
>>>>>>>>> crack open a *for* or for a *with* that I need to be using *<-* .
>>>>>>>>> I've just internalized it as the "powerful SpecialForms clause 
>>>>>>>>> operator".
>>>>>>>>> So I don't think allowing its use in other powerful new constructs,
>>>>>>>>> potentially nested in *for* or *with*, or inside their options
>>>>>>>>> lists, would be confusing, from my perspective at least.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> 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/72ee4929-efde-476e-9124-bacd7460c486n%40googlegroups.com
>>>>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/72ee4929-efde-476e-9124-bacd7460c486n%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-co...@googlegroups.com.
>>>>>>>>
>>>>>>> To view this discussion on the web visit
>>>>>>>> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BsbvBxoj1mECXzBna%3DJE-R8%2Bj-CBuRZvgAf%2BsLp2aMjw%40mail.gmail.com
>>>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BsbvBxoj1mECXzBna%3DJE-R8%2Bj-CBuRZvgAf%2BsLp2aMjw%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/10d18915-55da-4b52-8e12-0992625039e3n%40googlegroups.com
>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/10d18915-55da-4b52-8e12-0992625039e3n%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/kxaott2e.e380bedb-a7bd-4f10-8d2c-573d453c6880%40we.are.superhuman.com
>>>> <https://groups.google.com/d/msgid/elixir-lang-core/kxaott2e.e380bedb-a7bd-4f10-8d2c-573d453c6880%40we.are.superhuman.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/CAGnRm4KYBajtuG0sAA%2BOtaWDo8AKn5csz6irK3f-Y1BLmrqvbw%40mail.gmail.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KYBajtuG0sAA%2BOtaWDo8AKn5csz6irK3f-Y1BLmrqvbw%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/kxaprh1k.8bfd20dc-9ccf-46d7-b01a-9746ae11d488%40we.are.superhuman.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/kxaprh1k.8bfd20dc-9ccf-46d7-b01a-9746ae11d488%40we.are.superhuman.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/CAGnRm4J76nw50ZdK2qShwgP0sdxehJCnjA6_giJLsR1OuFqZjA%40mail.gmail.com.

Reply via email to