<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="237031" data-post-id="237031">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="LostKobrakai" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/LostKobrakai/120/3072_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  LostKobrakai
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="benwilson512" data-post="42" data-topic="44773">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benwilson512/48/1457_2.png" class="avatar"> benwilson512:</div>
<blockquote>
<p>Particularly the <code>sum = sum</code> bit to sort of emphasize the rebinding significance. I think I can get behind that actually.</p>
</blockquote>
</aside>
<p>Exactly. Just like you cannot do <code>for a do</code> to shorten <code>for a &lt;- a do</code>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237031" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/43">Post #42</a>
	                </div>
	            </div>
              <div id="likers-container-237031" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237031"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #42"></div>
  </section>
</div>
    <div class="postbit" id="237032" data-post-id="237032">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mgibowski" data-post="38" data-topic="44773">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mgibowski/48/21221_2.png" class="avatar"> mgibowski:</div>
<blockquote>
<p>This could be confusing to users, as somebody could try to use the let variable after the <code>for_loop</code> and could expect the value to be the same as the last one in the loop.</p>
</blockquote>
</aside>
<p>While I can see this is confusing, it is not different from anything else in Elixir. You can still also write this (and I suspect many new users do):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">sum = 0

if true do
  sum = 1
end

sum
</code></pre>
<p>But everyone quickly learns that the value inside the block does not affect values outside the block.</p>
<aside class="quote no-group" data-username="mgibowski" data-post="38" data-topic="44773">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mgibowski/48/21221_2.png" class="avatar"> mgibowski:</div>
<blockquote>
<p>I doubt there is anything to be done about it, but I will share my impression from reading this block of code the first time.</p>
</blockquote>
</aside>
<p>One way to read this is that the first argument is the argument of <code>for</code>, the second is <code>let</code>. But, as per the discussion above, the only option that would make this clear is calling it <code>map_reduce</code> instead of <code>let</code>. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237032" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/44">Post #43</a>
	                </div>
	            </div>
              <div id="likers-container-237032" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237032"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #43"></div>
  </section>
</div>
    <div class="postbit" id="237033" data-post-id="237033">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="benwilson512" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benwilson512/120/1457_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  benwilson512
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Craft GraphQL APIs in Elixir with Absinthe</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>So here’s a thought on the whole <code>for</code> and <code>map_reduce</code> thing. <code>for</code> <em>already</em> is a bit of a shape shifter. Specifically I guess I’m objecting to this interpretation of how it reads:</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="44773">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>In my mind, “for” already means “map”, because that’s what it does by default. So “for map_reduce” is, in a way, the equivalent to “map map_reduce”.</p>
</blockquote>
</aside>
<p>I don’t think this is actually right. If it were, <code>for reduce x = 1</code> should be read <code>map reduce</code> which is exactly what it <em>doesn’t</em> do, it just reduces. <code>for</code> does a <em>bunch</em> of stuff already, it’s a collection iterator tool. It basically says “we’re going to iterate over some stuff” and then if you use <code>x &gt; 1</code> in there it also filters, and if you do <code>reduce</code> it reduces. If you use <code>into</code> it does a reduce-like thing into a collection.</p>
<p>Where this leaves me is that I think <code>map_reduce</code> has a good case. Sure, a very literal reading of <code>for map_reduce</code>  feels a bit redundant but I think that hyper literal reading is simply wrong in the general case. The big upside of <code>map_reduce</code> is that it</p>
<ol>
<li>Doesn’t introduce a term that is used nowhere else (let, given, etc)</li>
<li>Uses a term (and return value shape) that is very common and is also used by Enum.map_reduce and friends.</li>
</ol>
<p>It’s not the prettiest or cleverest answer, but that’s OK. I hear your concerns about people not knowing what map_reduce is at the start, but they won’t know what <code>let</code> is either, and will have to figure it out from how the comprehension operates. When they’re done, they’ll have learned something they can take elsewhere in the language.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237033" data-batch-url="/posts/batch_likers">
                        8
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/45">Post #44</a>
	                </div>
	            </div>
              <div id="likers-container-237033" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237033"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #44"></div>
  </section>
</div>
    <div class="postbit" id="237045" data-post-id="237045">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="stevensonmt" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevensonmt/120/20503_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  stevensonmt
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="28" data-topic="44773">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<pre data-code-wrap="elixir"><code class="lang-elixir">for init(sum = 0), x &lt;- [1, 2, 3] do
  {x * 2, sum + x}
end
</code></pre>
</blockquote>
</aside>
<p>what about <code>for with_init sum = 0, x &lt;- [1,2,3] do ...</code>? Or even better to my ear is</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for x &lt;- [1,2,3],
  with_init sum = 0 do 
    {x * 2, sum + x}
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237045" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/46">Post #45</a>
	                </div>
	            </div>
              <div id="likers-container-237045" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237045"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #45"></div>
  </section>
</div>
    <div class="postbit" id="237056" data-post-id="237056">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="massimo" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/massimo/120/5555_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  massimo
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="benwilson512" data-post="45" data-topic="44773">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benwilson512/48/1457_2.png" class="avatar"> benwilson512:</div>
<blockquote>
<p>It’s not the prettiest or cleverest answer, but that’s OK. I hear your concerns about people not knowing what map_reduce is at the start, but they won’t know what <code>let</code> is either, and will have to figure it out from how the comprehension operates. When they’re done, they’ll have learned something they can take elsewhere in the language</p>
</blockquote>
</aside>
<p>I was trying to write a macro that translated this</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex&gt; for let sum = 0, i &lt;- [1, 2, 3] do
...&gt;   sum = sum + i
...&gt;   {i * 2, sum}
...&gt; end
{[2, 4, 6],  6}
</code></pre>
<p>to this</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex&gt; Enum.map_reduce([1, 2, 3], %{sum: 0}, fn i, %{sum: sum} = acc -&gt; 
...&gt;   {i * 2, %{acc | sum: sum + 1}}
...&gt; end)
...&gt;|&gt; then(fn {map, %{sum: sum}} -&gt; {map, sum} end)
{[2, 4, 6], 6}
</code></pre>
<p>that can be simplified to in this case</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex&gt; Enum.map_reduce([1, 2, 3], 0, fn i, sum -&gt; 
...&gt;   {i * 2, sum + 1}
...&gt; end)
{[2, 4, 6], 6}
</code></pre>
<p>and I realized that the <code>Enum.map_reduce</code> is actually not that bad if you have ever coded in Elixir</p>
<p>if <code>Enum.map_reduce</code> was imported somewhere, it boils down to</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex&gt; map_reduce([1, 2, 3], 0, fn i, sum -&gt; 
...&gt;   {i * 2, sum + i}
...&gt; end)
{[2, 4, 6], 6}
</code></pre>
<p>or with more than one variable</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">iex&gt; map_reduce([1, 2, 3], {0, 0}, fn i, {sum, count} -&gt; 
...&gt;   {i * 2, {sum + i, count + 1}}
...&gt; end)
{[2, 4, 6], {6, 3}}
</code></pre>
<p>I mean, there are times when Elixir can look verbose, but this solution to the <a href="https://github.com/josevalim/nested-data-structure-traversal/blob/master/elixir/map_reduce.exs" rel="noopener nofollow ugc">nested data structure traversal problem</a> is 13 lines long and In my opinion it’s not a clever but unreadable solution, on the contrary I think it’s pretty straightforward (and more idiomatic Elixir than the <code>for-let</code> one, but that’s just my opinion.)</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{sections, _} = Enum.map_reduce(sections, {1, 1}, fn %{"lessons" =&gt; lessons} = section, {sc, lc} -&gt;
    lc = if section["reset_lesson_position"], do: 1, else: lc

    lessons = lessons
      |&gt; Enum.with_index(lc)
      |&gt; Enum.map(fn {lesson, p} -&gt; Map.put(lesson, "position", p) end)

    section = Map.merge(section, %{"lessons" =&gt; lessons, "position" =&gt; sc})

    {section, {sc + 1, lc + Enum.count(lessons)}}
  end)

sections
</code></pre>
<p>I stay positive about the introduction of a <code>for-let</code> and a <code>for-reduce</code> pattern and, despite my comments, it doesn’t really matter what name or form will be chosen, given the track record of the Elixir core team, I’m more than confident that the best solution will be the one adopted in the end.</p>
<p>On a final note: If the main concern was that <code>for-let</code> is more readable, reduces the clutter and can eventually drive adoption, my advice  is to also take a look at the ergonomics of the most used functions (<code>Enum</code> and <code>Map</code> module for example) and think how improve on them.</p>
<p>IMO simply removing the need to always prefix the module name for some of the fundamental ones, Elixir would look 30% less noisy.</p>
<p>Look for example at this once <code>Enum</code> and <code>Map</code> have been imported</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">
{sections, _} = map_reduce(sections, {1, 1}, fn %{"lessons" =&gt; lessons} = section, {sc, lc} -&gt;
  lc = if section["reset_lesson_position"], do: 1, else: lc

  lessons = lessons
    |&gt; with_index(lc)
    |&gt; map(fn {lesson, p} -&gt; put(lesson, "position", p) end)

  section = merge(section, %{"lessons" =&gt; lessons, "position" =&gt; sc})

  {section, {sc + 1, lc + count(lessons)}}
end)

</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237056" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/47">Post #46</a>
	                </div>
	            </div>
              <div id="likers-container-237056" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237056"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #46"></div>
  </section>
</div>
    <div class="postbit" id="237094" data-post-id="237094">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="gregvaughn" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/gregvaughn/120/954_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  gregvaughn
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><strong>Point 1:</strong> Business communication in English has long used the abbreviation “RE” which is short for “regarding” or “in reference to this other thing”. Email picked up on this pre-existing terminology and that’s why email replies will alter the subject to “RE: <em>original subject</em>”.</p>
<p><strong>Point 2:</strong> Elixir has the convention of using bang (!) to draw attention to a function. It can raise an exception. I think of it as indicating “pay extra attention to what you’re doing here”.</p>
<p><strong>Therefore</strong>, we could consider something like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for re! sum = 0, i &lt;- [1, 2, 3] do ...
</code></pre>
<p>So when we’re code golfing, we can yell “FORE!” as golfers do when they tee off.<br>
<img src="https://forum.elixirforum.com/uploads/default/original/2X/4/425cf8a2af1868cc834c0a12b6f0c9ef0e530de9.gif?v=15" title=":icon_biggrin:" class="emoji emoji-custom only-emoji" alt=":icon_biggrin:" loading="lazy" width="20" height="20"> <img src="https://forum.elixirforum.com/uploads/default/original/2X/4/425cf8a2af1868cc834c0a12b6f0c9ef0e530de9.gif?v=15" title=":icon_biggrin:" class="emoji emoji-custom only-emoji" alt=":icon_biggrin:" loading="lazy" width="20" height="20"> <img src="https://forum.elixirforum.com/uploads/default/original/2X/4/425cf8a2af1868cc834c0a12b6f0c9ef0e530de9.gif?v=15" title=":icon_biggrin:" class="emoji emoji-custom only-emoji" alt=":icon_biggrin:" loading="lazy" width="20" height="20"></p>
<p><em>I’ll see myself to the door now</em></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237094" data-batch-url="/posts/batch_likers">
                        7
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/48">Post #47</a>
	                </div>
	            </div>
              <div id="likers-container-237094" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237094"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #47"></div>
  </section>
</div>
    <div class="postbit" id="237102" data-post-id="237102">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="thiagomajesk" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/thiagomajesk/120/31904_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  thiagomajesk
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’ve been reimplementing the examples so I can have a better visualization of the proposal. I think the intention behind allowing the user to represent the “returning shape” of the comprehension instead of having to accumulate the values is interesting for all intents and purposes.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for i &lt;- [1, 2, 3], reduce: {[], 0} do
	{list, sum} -&gt; {[i * 2 | list], sum + i}
end

# over

for let sum = 0, i &lt;- [1, 2, 3] do
  sum = sum + i
  {i * 2, sum}
end
</code></pre>
<p>And</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">element = ["a", "b", "c", "d", "e"]

for i &lt;- element, reduce: {[], 0} do
  {list, count} when count &lt; 3 -&gt; {[i | list], count + 1}
  {list, count} -&gt; {list, count}  
end

# over

for let count = 0, count &lt; 5, x &lt;- element do
  {x, count + 1}
end
</code></pre>
<p>I think everyone can agree with that, the examples in the proposal are objectively clear. However, I feel that at this point, the discussion is going in another direction (I t tried to expand on that in the previous post)… By changing the default behavior of <code>for</code> it almost feels like we are talking about another thing completely. I’d very much rather have this as a different approach, perhaps a secondary keyword to deal with this specific scenario, like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">yield sum = 0, i &lt;- [1, 2, 3] do
  sum = sum + i
  {i * 2, sum}
end

yield count = 0, count &lt; 5, x &lt;- element do
  {x, count + 1}
end
</code></pre>
<p>PS.: Doing this little conceptual exercise quickly reminded me of js generators and C#'s <code>yield</code>, which works similarly (-ish).</p>
<p>It would be considered the same as comprehensions go, but being clear that the expected output of the block is defined by the shape you pass as the first argument. This avoids introducing different “modes” to <code>for</code> and it seems simpler to explain because although it still works as a standard comprehension, it has a different signature altogether.</p>
<p>I think that perhaps this leaves space for expansion for options like for already does with <code>:uniq</code> and <code>:reduce</code>:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">yield count = 0, count &lt; 5, x &lt;- element, async: true do
  {x, count + 1}
end
</code></pre>
<p>I don’t know if introducing a new keyword is a dealbreaker to <a class="mention" href="/u/josevalim" rel="nofollow">@josevalim</a>, but it seems (to me at least) easier to reason about than introducing multiple modes in something that it’s already very much easy to understand by itself.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237102" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/49">Post #48</a>
	                </div>
	            </div>
              <div id="likers-container-237102" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237102"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #48"></div>
  </section>
</div>
    <div class="postbit" id="237105" data-post-id="237105">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you <a class="mention" href="/u/thiagomajesk" rel="nofollow">@thiagomajesk</a> for the detailed follow up. Introducing a new word will most likely cause some breakage. How much it depends on the word. The issue is that, because we have two modes (map_reduce/reduce), at least two words would be required and that may be a bit too much.</p>
<p>One way to see <code>for let</code> and <code>for reduce</code> is as a mechanism to avoid introducing new keywords. Although I think <code>for_let</code> and <code>for_reduce</code> should be pretty safe to introduce, conflict-wise.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237105" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/50">Post #49</a>
	                </div>
	            </div>
              <div id="likers-container-237105" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237105"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #49"></div>
  </section>
</div>
    <div class="postbit" id="237108" data-post-id="237108">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dorgan" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dorgan/120/22107_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dorgan
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I tried quite hard to find counter examples to this proposal, but after writing them I realize that they aren’t big deals or they are non issues.</p>
<p>With regular <code>for</code> you can first read the generators and filters, and then read the body of the comprehension. What you get in the body happens after all of the generators and filters were applied:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for x &lt;- xs,
    foo?(x),
    bar?(x) do
  # do something with x
end
</code></pre>
<p>With the introduction of <code>let</code>, I could argue that suddenly that’s no longer the case, the stuff we extract from the generators may change, or the filter turns into an exit condition, not a filter. This may lead to some confusion but then:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for let count = 0,
    x &lt;- xs,
    foo?(x) and count &lt;= 10 do
  # do something with x and count
end
</code></pre>
<p>And it’s not hard to see what’s happening. What is confusing though, is that it’s not clear if this will cause all <code>x</code>s to be discarded because the filter returns false and the <code>xs</code> will be fully traversed, or it will lazily collect values from <code>xs</code> and abort the comprehension when the filter returns false.</p>
<p>Most of the examples shown here either bind a single variable, or use pattern matching with tuples. I could argue that it gets nasty very quickly with very long tuples and that it’s horrible having to figure out the position of a value in a tuple and where it binds to, but then you can do this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{result, state} =
  for let state = %{a: 1, b: :foo, c: []},
      x &lt;- xs do
    # ...
    state = %{state | c: [x + 1 | state.c]}
      {x, state}
  end

baz = state.c # ...
</code></pre>
<p>So again, not an issue.</p>
<p>So yeah, the only issue I see with the proposal is the lack of consensus over the “qualifier” name. The fact that <code>let</code> would be a function with special meaning to <code>for</code> is kind of alien to the way the rest of the language works, but when I try to imagine myself using it I don’t find it too much of an issue.</p>
<p>In any case, we can achieve the same today with map_reduce as you mentioned. Looking at the picture showing boilerplate vs what we actually care about:<br>
</p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/e/8/e84400efcacf7a170aad4bc3365191d916676e07.png" data-download-href="https://forum.elixirforum.com/uploads/default/e84400efcacf7a170aad4bc3365191d916676e07" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/e/8/e84400efcacf7a170aad4bc3365191d916676e07_2_690x434.png" alt="image" data-base62-sha1="x8It9SoSFOUiZOWMMJs3LnSdIFh" width="690" height="434" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/e/8/e84400efcacf7a170aad4bc3365191d916676e07_2_690x434.png, https://forum.elixirforum.com/uploads/default/original/3X/e/8/e84400efcacf7a170aad4bc3365191d916676e07.png 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/e/8/e84400efcacf7a170aad4bc3365191d916676e07.png 2x" data-dominant-color="F2F0F0"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">729×459 43.1 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><br>
And then again at the proposed code:<p></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">section_counter = 1
lesson_counter = 1
{sections, _acc} =
  for let {section_counter, lesson_counter}, section &lt;- sections do
    lesson_counter = if section["reset_lesson_position"], do: 1, else: lesson_counter
    
    {lessons, lesson_counter} =
      for let lesson_counter, lesson &lt;- section["lessons"] do
        {Map.put(lesson, "position", lesson_counter), lesson_counter + 1}
      end
    
    section =
      section
      |&gt; Map.put("lessons", lessons)
      |&gt; Map.put("position", section_counter)

    {section, {section_counter + 1, lesson_counter}}
  end
</code></pre>
<p>In terms of boilerplate reduction, I’m not sure there’s a substantial win. However, that aside, the benefits this proposal offers are, if I understand correctly:</p>
<ol>
<li>Allow to exit early from the comprehension by using the <code>let</code> bindings in filters(so, sort of a reduce_while)</li>
<li>Allow “accumulator” or “state” value and binding to be defined in the same expression</li>
</ol>
<p>I think 1 is the most important, as it enables more powerful patterns. I’m not entirely sure we are making a significant improvement in removing boilerplate, though. Honestly, I think it still looks ugly compared to python. The original proposal in the mailing list did address this issue, but it was too magical.</p>
<p>So in summary: the new syntax doesn’t feel wrong to me, and I’m interested in the new patterns it enables, but I’m not convinced that it reduces boilerplate, thus I’m not sure it would improve the situation for newcomers save for the “exit early” case.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237108" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/51">Post #50</a>
	                </div>
	            </div>
              <div id="likers-container-237108" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237108"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #50"></div>
  </section>
</div>
    <div class="postbit" id="237110" data-post-id="237110">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="thiagomajesk" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/thiagomajesk/120/31904_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  thiagomajesk
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hey <a class="mention" href="/u/josevalim" rel="nofollow">@josevalim</a>, no problem at all. I have to say that I’m kinda surprised, which kind of breakage are you talking about? I think that other people might also be curious now that you mentioned it. My first instinct would be to think that introducing a new keyword as a new feature would be easier than actually modifying the behavior of an existing one (but I don’t really know the elixir codebase enough to be sure).</p>
<p><strong>Update</strong>: I was thinking about <code>Enum.chunk_while/4</code> and <code>Enum.group_by/3</code>, where you have better control on how to emmit chunks and change the resulting values, and I was thinking if this could be applicable here. So, instead of creating two different “modes”, what about treating the emitted values in a different way?</p>
<p>If I had to implement this in a simple function I’d rather have a transformation bein applied to the values after each emission:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># only map values (accumulating)
fun1 = fn v1, v2, {list, sum} -&gt; { [v1|list], v2 + sum} end

yield {list, sum}, i &lt;- [1, 2, 3], init: {[], 0}, fun: fun1 do
  {i * 2, sum + 1}
end

# keep values as-is (could be the default implementation)
fun2 = fn _v1, _v2, {sum, count} -&gt; { sum,  count} end

yield {sum, count}, i &lt;- [1, 2, 3], init: {0, 0}, fun: fun2 do
  {sum + i, count + 1}
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237110" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/52">Post #51</a>
	                </div>
	            </div>
              <div id="likers-container-237110" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237110"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #51"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/44773/load_more?page=6">Load more posts (73 remaining)</a>
</div></template></turbo-stream>