{"id":2161,"date":"2022-03-18T22:05:32","date_gmt":"2022-03-19T03:05:32","guid":{"rendered":"http:\/\/www.ishygddt.xyz\/~blog\/?p=2161"},"modified":"2023-01-30T19:15:41","modified_gmt":"2023-01-31T01:15:41","slug":"elixir-basic-while-loop","status":"publish","type":"post","link":"http:\/\/www.ishygddt.xyz\/~blog\/2022\/03\/elixir-basic-while-loop","title":{"rendered":"Basic \"while\" loop in Elixir"},"content":{"rendered":"<p>Given this Python code:<\/p>\n<pre><code class=\"language-python\" data-line=\"\">def f(k):\n\tn = 2 &lt;&lt; k\n\tq = 2\n\ti = 1\n\twhile q != n:\n\t\t\n\t\ti *= q\n\t\t\n\t\tq &lt;&lt;= 1\n\treturn i<\/code><\/pre>\n<p>The Elixir translation is roughly the following:<\/p>\n<pre><code class=\"language-elixir\" data-line=\"\">def f(k) do\n\tn = 2 &lt;&lt;&lt; k # Remember to add &quot;use Bitwise&quot; at the top of the module\n\tq = 2\n\ti = 1\n\t# (Storing the output into a tuple for reasons that will be explained later)\n\t{i, _, _} = Stream.unfold({q, i}, fn # Initial values: current scope&#039;s q and i\n\t\t{^n, _} -&gt; nil # Loop halt condition: q == n (fixing the current scope&#039;s value of n)\n\t\t{q, i} -&gt; # Loop takes 2 arguments: q, i (inside a tuple)\n\t\t\t\n\t\t\ti = i * q\n\t\t\t\n\t\t\t{ # Return a 2-tuple to the `Stream.unfold` interface:\n\t\t\t\t# 1st element gets yielded to the outer scope:\n\t\t\t\t{i, :fyi, &quot;You can return multiple values here if you want to&quot;},\n\t\t\t\t# 2nd element is fed back in as the argument to the next iteration of the loop:\n\t\t\t\t{q &lt;&lt;&lt; 1, i}\n\t \t\t}\n\tend)\n\t|&gt; Enum.take(-1) # Stream.unfold yields all values; only take the last\n\t|&gt; hd # Convert 1-element list into its component element\n\ti\nend<\/code><\/pre>\n<p>Generalizing further, we get:<\/p>\n<pre><code class=\"language-elixir\" data-line=\"\">hd(Enum.take(Stream.unfold({nil, VARS}, fn\n\t{:halt, _} -&gt; nil\n\t{_, VARS} -&gt;\n\t\tWHILE_BODY(VARS) # _do_ modify VARS within this\n\t\t{RETVAL(VARS), {if(EXIT_PREDICATE(VARS), do: :halt), VARS}}\nend), -1))<\/code><\/pre>\n<p>(where <code class=\"language-elixir\" data-line=\"\">VARS<\/code> may be either a bare variable or a tuple of them)<\/p>\n<p>TODO: translate that last codeblock into <code class=\"language-elixir\" data-line=\"\">defmacro while\u2026<\/code><\/p>\n<hr \/>\n<p>Of course, the above code is a <strong>maximalist, generalizable example<\/strong>\u2014it is a <strong>template<\/strong> that you can take and fill with the most convoluted looped code you care to write (so long as you enumerate the variables that get changed each loop and shunt them away into the return value); in reality, computing the above function <em>per se<\/em> would be very simple since it's inherently a kind of accumulation; something like the following would do:<\/p>\n<pre><code class=\"language-elixir\" data-line=\"\">def f(k) do\n\tq = 2\n\tEnum.product(Stream.map(0..(k-1), fn k -&gt; (q &lt;&lt;&lt; k) end))\nend<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\"that's not how you're supposed to use functional programming languages\" &#8212; how 'bout I do anyway?<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-2161","post","type-post","status-publish","format-standard","hentry","category-drafts"],"_links":{"self":[{"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/posts\/2161","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/comments?post=2161"}],"version-history":[{"count":43,"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/posts\/2161\/revisions"}],"predecessor-version":[{"id":2479,"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/posts\/2161\/revisions\/2479"}],"wp:attachment":[{"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/media?parent=2161"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/categories?post=2161"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.ishygddt.xyz\/~blog\/wp-json\/wp\/v2\/tags?post=2161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}