dominicletz

dominicletz

Creator of Elixir Desktop

While - Elixir macro for ruby traditional while - looking for feedback

Hi Guys,
one more time I had this need for a simple while loop and so I played with this macro idea: https://hex.pm/packages/while

While on globals

  import While

  ref = :counters.new(1, [:atomics])
  while :counters.get(ref 1) < 10 do
    :counters.add(ref 1, 1)
  end

  IO.puts("Current value is #{:counters.get(ref, 1)}")

Now this only works when you’re working with globals, references or pids, which in fact in my case is useful sometimes. But to make it more useful in local scopes I created a more reduce like shortcut:

While on locals

When providing an additional parameter, this is interpreted as a variable name and imported into the scope of the while expression and the while body.

    import While

    cnt = 1
    cnt = while cnt, cnt < 10 do
      cnt + 1
    end

    IO.puts("Current value is #{cnt}")

Explanation:
The while/3 binds the variable name cnt to both the expression cnt < 10 and to the body. The body result (last line of body) always becomes the new value for the bound variable, like in a Enum.reduce.

   cnt - 1

Danger Area

To automate the assignment, there is another variant while_with that will automagically assign to the original variable. Consensus from this discussion seems to be: Don’t use this variant

    import While

    cnt = 1
    while_with cnt, cnt < 10 do
      cnt + 1
    end

    IO.puts("Current value is #{cnt}")

Explanation:
The while_with works exactly like while/3 but the final value, will be assigned to the bound variable of the outer scope, so that: IO.puts("Current value is #{cnt}") will print Current value is 10

Questions
The name while_with might be confusing, should this just be the same name, but a two parameter variant of while , or should it be called reduce_while or something? Curious about the communities thoughts here and whether this kind of macro has any reason to exist at all in the first place :slight_smile:

Installation
While can be installed by adding while to your list of dependencies in mix.exs:

def deps do
  [
    {:while, "~> 0.2.1"}
  ]
end

Most Liked

sasajuric

sasajuric

Author of Elixir In Action

You don’t need to write an explicit recursive function. The same can be achieved with e.g.:

Stream.repeatedly(fn -> worker_online() == target end)
|> Enum.find(& &1)
benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Can you elaborate on these concrete use cases? I really can’t think of any situation where I wouldn’t prefer a recursive function, or the use of Enum.

    cnt = 1
    while_with cnt, cnt < 10 do
      cnt + 1
    end

    IO.puts("Current value is #{cnt}")

The hidden rebinding here is particularly alarming since it changes core expectations people have about how Elixir code works. It’s also presumably inconsistent right? What if you do:

i = 0
j = 0
    while_with i, i < 10 do
      i + 1
      j + 1
    end

Is i incremented to 10, but j not?

dominicletz

dominicletz

Creator of Elixir Desktop

Thanks all for the feedback. I’ve removed while_with from the examples and marked it deprecated - because the hidden assignment indeed seems too dangerous.

For those who still want to use while the way to go is the while/3 macro that returns the value, so the assignment is visible in the code:

    cnt = 1
    cnt = while cnt, cnt < 10 do
      cnt + 1
    end
sasajuric

sasajuric

Author of Elixir In Action

To make this happen, you could do something like:

Stream.repeatedly(&start_new_worker/0)
|> Enum.take(max(target - workers_online(), 0))
LostKobrakai

LostKobrakai

There’s already Enum.reduce_while, so I’m not sure how good of a name this one would be.

Where Next?

Popular in Libraries Top

grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
praveenperera
FastRSS Parse RSS feeds very quickly: This is rust NIF built using rustler Uses the RSS rust crate to do the actual RSS parsing Speed...
New
kelvinst
Hey everyone! Well, we made this lib a while ago and now we decided to finally go out and public with it! It’s a tool for creating and m...
New
archan937
It is a well-know topic within the Elixir community: “To mock or not to mock? :)” Every alchemist probably has his / her own opinion con...
New
mindok
What is ContEx? A pure Elixir server-side data plotting/charting library outputting SVG. It has nice barcharts in particular and works g...
New
michalmuskala
Another small library today. PersistentEts Hex: persistent_ets | Hex GitHub: GitHub - michalmuskala/persistent_ets Ets table backed by...
New
riverrun
I’ve just released version 3 of Comeonin, a password hashing library. The following small changes have been made: changes to the NIF c...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
Antrater
Hi everyone! I’m thrilled to announce a huge thing. We have been developing Elixir Moon Design System for quite a while. We are finally ...
New
bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
381 12391 119
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

Sub Categories:

We're in Beta

About us Mission Statement