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. daniel@ gmail. com
> ( 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 < evangelistajoaop@
>> gmail. com ( 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 (
>>> 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
>>>>> ( 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+unsubscribe@ googlegroups. com (
>>> 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+unsubscribe@ googlegroups. com (
>> 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+unsubscribe@ googlegroups. com (
> 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.

Reply via email to