<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="237201" data-post-id="237201">
  <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 group-livebook_core_team" data-username="josevalim" data-post="70" 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>I could go on and on. If we didn’t have <code>for</code>, all of those snippets would be <strong>worse, noisier, and also slower</strong>.</p>
</blockquote>
</aside>
<p>Is there a reason why they are slower?</p>
<p>Aren’t they implemented with the same core instructions?</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="70" 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><a href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/57" rel="nofollow">I have already posted examples of how the proposal can improve existing code</a>.</p>
</blockquote>
</aside>
<p>Just for fun I re-implemented some of the examples in two drastically different ways.</p>
<p>For me, for example, Elixir is a great fit because I usually think in terms of pipelines and it gives me the tools to express what I want, almost bit per bit.</p>
<p>The second reason is that in Elixir tooling has been there from day one, to solve any possible problem, you just have to dig a little bit.</p>
<p>And in every release new <code>utility functions</code> have been added to make things easier.</p>
<p>So, for example, this</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  Enum.flat_map_reduce(subs, sources, fn sub, sources -&gt;
    sub_formatter = Path.join(sub, ".formatter.exs")

    if File.exists?(sub_formatter) do
      formatter_opts = eval_file_with_keyword_list(sub_formatter)

      {formatter_opts_and_subs, sources} =
        eval_deps_and_subdirectories(:in_memory, [sub], formatter_opts, sources)

      {[{sub, formatter_opts_and_subs}], sources}
    else
      {[], sources}
    end
  end)
</code></pre>
<p>can be rewritten as</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">subs
|&gt; Enum.filter(&amp;File.exists?(Path.join(&amp;1, ".formatter.exs")))
|&gt; Enum.flat_map_reduce(sources, fn sub, sources -&gt; 
  formatter_opts = eval_file_with_keyword_list(Path.join(sub, ".formatter.exs"))

  {formatter_opts_and_subs, sources} =
    eval_deps_and_subdirectories(:in_memory, [sub], formatter_opts, sources)

  {[{sub, formatter_opts_and_subs}], sources}
end)
</code></pre>
<p>or this</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def find_asset_info(notebook, hash) do
  Enum.find_value(notebook.sections, fn section -&gt;
    Enum.find_value(section.cells, fn cell -&gt;
      is_struct(cell, Cell.Elixir) &amp;&amp;
        Enum.find_value(cell.outputs, fn
          {:js_static, %{assets: %{hash: ^hash} = assets_info}, _data} -&gt; assets_info
          {:js_dynamic, %{assets: %{hash: ^hash} = assets_info}, _pid} -&gt; assets_info
          _ -&gt; nil
        end)
    end)
  end)
end
</code></pre>
<p>as</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def find_asset_info(notebook, hash) do
  filter = [
    :sections, all(), :cells,
    filter(&amp;is_struct(&amp;1, Cell.Elixir)),
    key(:outputs), all(), elem(1), :assets
  ]

  get_in(notebook, filter)
  |&gt; List.flatten()
  |&gt; Enum.find_value(fn
    %{hash: ^hash} = assets_info -&gt; assets_info
    _ -&gt; nil
  end)
end
</code></pre>
<p>admittedly an extreme example of some lesser-known Elixir facilities, but still pretty easy to follow</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237201" 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/73">Post #72</a>
	                </div>
	            </div>
              <div id="likers-container-237201" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237201"
                     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 #72"></div>
  </section>
</div>
    <div class="postbit" id="237209" data-post-id="237209">
  <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">
								<aside class="quote no-group" data-username="massimo" data-post="73" 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/massimo/48/5555_2.png" class="avatar"> massimo:</div>
<blockquote>
<p>Is there a reason why they are slower?</p>
</blockquote>
</aside>
<p>Nope, no reason :p. In all seriousness a lot of it boils down to this: The <code>for</code> special form (AKA fancy macro) is provided all of the relevant filters, generators, and so forth up front, and so it can emit compact code that accomplishes more with fewer iterations at compile time. Enum.* calls are functions, and only have access to the collection and the function at runtime. Stream can compose stuff but has similar issues where it all happens at runtime.</p>
<p>I say “issues” but that’s perhaps too strong; it’s a trade off.</p>
<p>For people objecting to <code>for</code> and a possible expansion of its functionality, have you used other functional languages? It’s extremely common in functional languages to have <em>at least</em> these core data structure manipulation mechanisms: raw recursion, basic functions, and then some sort of fancy list comprehension that ties a number of features together in an ergonomic way. Haskell, Clojure, Erlang, Scala (quasi-functional), F# all have these same three.</p>
<p>That isn’t to say that Elixir’s version is or needs to be exactly the same as the rest, but I think some of the points here basically argue that <code>for</code> itself is superfluous, and I think that’s a strange stance to take within the language ecosystem.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237209" data-batch-url="/posts/batch_likers">
                        9
                      </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/74">Post #73</a>
	                </div>
	            </div>
              <div id="likers-container-237209" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237209"
                     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 #73"></div>
  </section>
</div>
    <div class="postbit" id="237211" data-post-id="237211">
  <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="massimo" data-post="73" 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/massimo/48/5555_2.png" class="avatar"> massimo:</div>
<blockquote>
<p>Just for fun I re-implemented some of the examples in two drastically different ways.</p>
</blockquote>
</aside>
<p>Your examples show why they are usually slower. You are doing two traversals and computing the <code>Path.join/2</code> twice.</p>
<p><code>Path.join/2</code> is cheap, so it is fine, but if it was expensive, then changing the code to compute it once would be an extra pass and more noise, or you would have to revert to the original version. With <code>for</code>, you don’t have to juggle this. <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="237211" 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/75">Post #74</a>
	                </div>
	            </div>
              <div id="likers-container-237211" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237211"
                     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 #74"></div>
  </section>
</div>
    <div class="postbit" id="237217" data-post-id="237217">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Firstly I have to say how well written the guide is - I was reading it in-between doing other stuff yesterday and kept thinking to myself that if that’s what the rest of the guides are like (I haven’t actually read them for a few years now) then anyone new coming in to the language is in for a treat!!</p>
<p>With regards to the proposal, if this is still on the cards it’s my fave as well:</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="28" data-topic="44773" data-full="true">
<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>Because if…</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="28" data-topic="44773" data-full="true">
<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>The goal is to initialize variables to be used as state during the <code>for</code>. All variables initialized as part of the <code>for</code> must then be returned inside <code>do-end</code> block.</p>
</blockquote>
</aside>
<p>..then it just makes sense and is more immediately obvious of what it is or might be (to me at least). However Elixir is my first functional language so I appreciate I may not be seeing things from the same perspective as others.</p>
<p>I also like <code>set</code> <a href="https://forum.elixirforum.com/t/introducing-for-let-and-for-reduce/44773/60" rel="nofollow">as mentioned</a> by <a class="mention" href="/u/mgwidmann" rel="nofollow">@mgwidmann</a>.</p>
<p>Personally my favourite would be José’s version but the init at the end:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for x &lt;- [1, 2, 3], init(sum = 0) do
  {x * 2, sum + x}
end
</code></pre>
<p>Because the primary focus of the <code>for</code> is the first part, the initialised variables are just something to be used with it.</p>
<p>Having said that:</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="28" data-topic="44773" data-full="true">
<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>I don’t want to overreact but this may be my favorite option so far. <img src="https://forum.elixirforum.com/images/emoji/apple/sweat_smile.png?v=15" title=":sweat_smile:" class="emoji" alt=":sweat_smile:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>On this I would personally support whatever José and the ECT think is best because I am sure they will have a million things in their head that I almost certainly won’t (including further possible extensions to the language). As I said tho I don’t have the same kind of functional language background as many of you but I just thought it was worth adding my thoughts as my perspective might be representative of others in similar shoes.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237217" 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/76">Post #75</a>
	                </div>
	            </div>
              <div id="likers-container-237217" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237217"
                     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 #75"></div>
  </section>
</div>
    <div class="postbit" id="237221" data-post-id="237221">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="xsteve" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  xsteve
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I am new to Elixir and I followed the discussion of this proposal.</p>
<p>This version is also good to read and understand by me:</p>
<p>for x ← [1, 2, 3], init(sum = 0) do<br>
{x * 2, sum + x}<br>
end</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237221" 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/77">Post #76</a>
	                </div>
	            </div>
              <div id="likers-container-237221" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237221"
                     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 #76"></div>
  </section>
</div>
    <div class="postbit" id="237241" data-post-id="237241">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’ve tried to read the whole thread, but it was split between a few days…</p>
<p>I prefer the term <code>bind</code> over <code>let</code> over <code>init</code>, as “binding” is already an Elixir concept, but <code>let</code> has precedence in <code>heex</code> templates now, so I can see it becoming “more normal”. Indeed, this proposal can just “<em>make it normal</em>”.</p>
<p>After playing around, I think the initial proposal is my favourite. No parens and we’re “just pattern matching”.</p>
<p>What would occur when I do:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{doubled, sum} =
  for let {sum, _} = {0, 10}, i &lt;- [1, 2, 3] do # _ behaves "as normal" and _ is discarded?
    sum = sum + i
    {i * 2, sum}
  end
</code></pre>
<p>Honestly <code>let</code> (or <code>bind</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">) are fine. Both hide the eventual behaviour, but so does <code>init</code>, and <code>accumulator</code> is pretty wordy, if not preciser. <s>Maybe <code>carry</code> as in “carry this value between calls”.</s></p>
<p>Perhaps I would ask, is <code>let</code> transportable as concept to other forms? Is <code>bind</code>? Is <code>init</code>? Can a user familiar with <code>for</code> reckon against what <code>let</code>/<code>bind</code>/<code>init</code> means in other contexts? If we added <code>let</code> to <code>with</code> or <code>try</code>, can it follow the same conceptual train?</p>
<p>Why was <code>let</code> chosen in <code>heex</code>? Does that solidify the semantics of the term, in Elixir?</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># I know heex *is not* elixir, the language, but if we are intending to reduce the 
# burden on learning.
&lt;.form let={f}&gt;
  # "'let' means the value of f inside this 'block' comes from somewhere else",
  # pretty similar to for let x = 0 really.
&lt;/.form&gt;
</code></pre>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;.form bind={f}&gt;
  # "I know form() 'returns' something and I want to bind that to f in this block"
  # honestly let feels more intuitive here.
&lt;/.form&gt;
</code></pre>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;.form init={f}&gt;
  # "initialise .. ah, f with what comes from the form? or am I initialising the form with f?
  # (obviously i am biased :))
&lt;/.form&gt;
</code></pre>
<pre data-code-wrap="elixir"><code class="lang-elixir">try let {rescue, after} = {my_rescue_fn, my_after_fn} do
...
end
</code></pre>
<pre data-code-wrap="elixir"><code class="lang-elixir">try init(rescue = my_rescue, after = my_after_fn) do # weirdddd
...
end
</code></pre>
<p>I find the <code>init(sum = 0)</code> structure odd, with required parens. Nothing else is really written like that in Elixir, with a bind inside a function call (which is what it looks like), at least not that I’ve seen.</p>
<p>I dont think there was a discussion on multiple inputs to <code>init</code>. Am I calling</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for init({a, b} = {0, 10}), x &lt;- 1..3 do
  {x, {a + x, b - x}}
end
</code></pre>
<p>or</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># I assume this one
for init(a = 0, b = 10), x &lt;- 1..3 do
  {x, {a + x, b - x}}
end
</code></pre>
<p><code>for init({a, b} = {0, 10}), ...</code> reads as “do this pattern match and … call a function with … the result of the match? Is that true if they match or the values or …?”, <code>init(a = 0, b = 10)</code> is even worse IMO since it looks a lot like default arguments in other languages, used in the wrong context.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">a = 99
for init(a = 0, b = 10), x &lt;- 1..3 do
  # is a 99 or 0? A new user may wonder can I call init(a, b \\ 100)?
  {x, {a + x, b - x}}
end
</code></pre>
<blockquote>
<p>“Why can’t I call <code>var = init(y = 0)</code>? What does that even mean? Why doesn’t <code>DateTime.new(time = t, date = d)</code> work? Can I provide my own init function?”</p>
</blockquote>
<p>I get that you can explain <em>why</em> this function call isn’t a function call, but it feels like setting your own mouse traps in the dark.</p>
<p>Without the parens, it’s a bit less confusing because <code>init</code> takes on the shape of a language keyword, even it if’s not (forget that you can call most special forms with parens… most users wont know/ignore this).</p>
<p>Anyway…</p>
<p><a href="https://thumbs.gfycat.com/LastBrokenHorsefly-size_restricted.gif" class="onebox" target="_blank" rel="noopener nofollow ugc">https://thumbs.gfycat.com/LastBrokenHorsefly-size_restricted.gif</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237241" data-batch-url="/posts/batch_likers">
                        5
                      </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/78">Post #77</a>
	                </div>
	            </div>
              <div id="likers-container-237241" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237241"
                     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 #77"></div>
  </section>
</div>
    <div class="postbit" id="237242" data-post-id="237242">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I think also I have always been a bit uncomfortable about how for will implicitly skip over stuff that doesn’t match…  I guess mentally I’m expecting a matchError…  I have never been comfortable with how the subsequent predicates are implicitly filters without saying so, and also how for implicitly goes into “reduce” mode with the forward arrows.</p>
<p>If I had a magic wand mapreduce would look like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for {i &lt;- 1..20, bind: sum, init: 0}, filter: rem(i, 2) == 0 do
  {i, sum + i}
end #==&gt; {[2, 4, 6...], 110}
</code></pre>
<p>And for reduce it would be:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for reduce: i &lt;- 1..20, bind: sum, init: 0, filter: rem(i, 2) == 0 do
  sum + i
end # ==&gt; 110
</code></pre>
<p>And the plain old <code>for</code> would have to be explicit about filter predicates:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for i &lt;- 1..20, j &lt;- 1..20, filter: i &lt; j, filter: rem(i, 2) == 0 do
  {i, j}
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="237242" 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/79">Post #78</a>
	                </div>
	            </div>
              <div id="likers-container-237242" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237242"
                     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 #78"></div>
  </section>
</div>
    <div class="postbit" id="237251" data-post-id="237251">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>No one praised the error message so far? I think that’s <em>the</em> thing that makes it work <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p>
<p>as for voting,</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for init {sum, count}, ...
</code></pre>
<p>looks good. <code>for reduce</code> no so much. <code>returning: :reduce</code> is good enough though</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237251" 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/80">Post #79</a>
	                </div>
	            </div>
              <div id="likers-container-237251" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237251"
                     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 #79"></div>
  </section>
</div>
    <div class="postbit" id="237258" data-post-id="237258">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thanks for putting together a detailed &amp; well-presented proposal <img src="https://forum.elixirforum.com/images/emoji/apple/pray/6.png?v=15" title=":pray:t6:" class="emoji" alt=":pray:t6:" loading="lazy" width="20" height="20"></p>
<p>I’m for the most part happy with it but would like to share a couple aspects of it that felt a bit ‘off’ at first encounter &amp; would love to hear what others think:</p>
<ol>
<li>
<p>The implicit asymmetry between return value of single iteration and return value of whole comprehension as shown in screenshot below. The fact that first element of tuple accumulates via mapping while second element accumulates via reduction is not explicit and tripped me up<br>
</p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/c/e/ce695134018ffb452b6fa5344185473c8148cd9c.png" data-download-href="https://forum.elixirforum.com/uploads/default/ce695134018ffb452b6fa5344185473c8148cd9c" title="elixir_proposal" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/c/e/ce695134018ffb452b6fa5344185473c8148cd9c_2_690x123.png" alt="elixir_proposal" data-base62-sha1="trZZZTqDr2zJ6lJYAfsQANNuEoI" width="690" height="123" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/c/e/ce695134018ffb452b6fa5344185473c8148cd9c_2_690x123.png, https://forum.elixirforum.com/uploads/default/optimized/3X/c/e/ce695134018ffb452b6fa5344185473c8148cd9c_2_1035x184.png 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/c/e/ce695134018ffb452b6fa5344185473c8148cd9c.png 2x" data-dominant-color="EFE7F1"><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">elixir_proposal</span><span class="informations">1091×196 21.9 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><p></p>
</li>
<li>
<p>The case for <code>for reduce</code> doesn’t seem very compelling. AFAIK the same functionality can be accomplished with current <code>:reduce</code> option and it’s not clear to me what advantage the new syntax brings in this case?<br>
</p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/2/8/2869094306d0ae42c607b9e33a0083475214da56.png" data-download-href="https://forum.elixirforum.com/uploads/default/2869094306d0ae42c607b9e33a0083475214da56" title="elixir_proposal_2" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/2/8/2869094306d0ae42c607b9e33a0083475214da56_2_690x328.png" alt="elixir_proposal_2" data-base62-sha1="5Lu8xG4og8L71DdpNUakg2tG68e" width="690" height="328" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/2/8/2869094306d0ae42c607b9e33a0083475214da56_2_690x328.png, https://forum.elixirforum.com/uploads/default/optimized/3X/2/8/2869094306d0ae42c607b9e33a0083475214da56_2_1035x492.png 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/2/8/2869094306d0ae42c607b9e33a0083475214da56.png 2x" data-dominant-color="F2E9F2"><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">elixir_proposal_2</span><span class="informations">1085×516 42.7 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><p></p>
</li>
<li>
<p>Initialization before the comprehension: as others previously pointed out, I can see this leading to some confusion. For ex: seeing <code>for let lesson_counter, lesson &lt;- section["lessons"] do</code> somewhere in the codebase without <code>lesson_counter</code>’s initialization co-located, when it’s a variable that will potentially be updated in each iteration</p>
</li>
<li>
<p>One of the great things about Elixir is the focus on explicitness and I’m a bit concerned we would be giving up some ground here with some aspects of the proposed solution, ex: use of tuple as return value with implicit reliance on position within the tuple for things like error messages. The examples used reductions over simple values like integers but would <code>ComprehensionError</code> for instance still work with values like nested tuples that could end up looking like valid output?</p>
</li>
</ol> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="237258" 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/81">Post #80</a>
	                </div>
	            </div>
              <div id="likers-container-237258" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237258"
                     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 #80"></div>
  </section>
</div>
    <div class="postbit" id="237260" data-post-id="237260">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>What if <code>for</code> “magically” scooped up re-bound <code>let</code> variables and returned them at the end without needing to explicitly return them inside the <code>for</code>?</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">for let count = 0, sum = 0, i &lt;- [1, 2, 3] do
  sum = sum + i
  count = count + 1
  i * 2
end

# returns {[2, 4, 6], %{sum: 6, count: 3}}
</code></pre>
<p><strong>You can re-bind the <code>let</code> variables in each iteration, and at the end <code>for</code> scoops up the final values and returns them in a map.</strong></p>
<p>To me, the original proposal where you have to return a tuple is destined to be confusing. Folks are used to whatever you return inside <code>for</code> getting put in a list. It’s bizarre to me that you’d do that and it would gather the first part of the tuple in a list, but “discard” the 2nd part until the final iteration.</p>
<p>My proposal above involves “magic” (implicit) behavior, but to me seems less confusing than the tuple convention.</p>
<p>If returning a map is controversial, maybe we can return a tuple instead:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{[2, 4, 6], {6, 3}}
</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="237260" 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/82">Post #81</a>
	                </div>
	            </div>
              <div id="likers-container-237260" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="237260"
                     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 #81"></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=9">Load more posts (43 remaining)</a>
</div></template></turbo-stream>