aadeshere1

aadeshere1

Write while loop equivalent in elixir

I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible.

total = 10
while total != 0
   puts "hello"
   total -= 1
end

The question and answer in this example use list for loop. Convert ruby while loop into elixir

Most Liked

sribe

sribe

I just want to comment on something, at first glance all the solutions posted on this page look kind of complicated for such a simple thing. But you almost never need to write such code in the real world.

In actual apps, you want to iterate over some collection of data items. The for or while loop is how you do that in an imperative language: you have some “iterator” kind of value–a simple index for an array, something else for a map or set–increment that, check if it’s out of range, use it to access your data collection.

In functional languages, you pass the operation you want to perform on the data as an argument to one of the collection’s functions. In Elixir, Enum.map or Enum.reduce. This actually results in more compact code because it eliminates the whole “get an iterator, increment, check it, use it” dance.

So while this particular exercise can help you understand some low-level mechanics of Elixir, it could also be misleading. Please don’t think you have to jump through the hoops of all these solutions in order to do something with an array of values you get back from your database or submitted from a web form :wink:

That said, here is my solution:

Enum.each(10..1, fn(i) -> IO.puts(i) end)

or, using some shorthand:

Enum.each(10..1, &(IO.puts("#{&1}")))

or, if you want to prove you actually understand passing around functions:

Enum.each(10..1, &IO.puts/1)

But even that could be misleading, because in a functional language you don’t often just “run a loop” over a collection for side effects, you usually produce a value, either a set of values produce from each source value (Enum.map) or a single value derived from the whole set (Enum.reduce).

13
Post #7
LostKobrakai

LostKobrakai

I found Stream.unfold to be quite useful for places where I don’t know how many iterations are needed to get to the end.

stream = Stream.unfold(10, fn x -> 
  if x != 0 do
    IO.puts "Hello"
    {:ok, x - 1}
  else
    nil
  end 
end)

Stream.run(stream)

There’s also Enum.reduce_while, but it needs an enumerable as input to start with.

10
Post #2
benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

@silverdr OK sure, here’s a non manual loop version:

Stream.repeatedly(&generate_name/0) |> Stream.take(16) |> Enum.find(&not_taken?/1)

This will return the first generated name that isn’t taken, OR quit after 16 tries. It will only generate as many names as are needed. Enumerable works great here too. Of course, you can always use manual recursion.

tme_317

tme_317

I think recursion is the simplest way to go…

defmodule Looper do
  def say_hello(times_left) do
    case times_left do
      0 ->
        :ok

      x ->
        IO.puts("hello")
        say_hello(x - 1)
    end
  end
end

Looper.say_hello(10)

You could use if instead of case since there are only two patterns.

Alternatively:

defmodule Looper do
  def say_hello(times_left) when times_left > 0 do
    IO.puts("hello")
    say_hello(times_left - 1)
  end

  def say_hello(times_left) when times_left == 0 do
    :ok  
  end
end

Looper.say_hello(10)
peerreynders

peerreynders

defmodule Demo do

  def while(pred, next, data) do
    case pred.(data) do
      true ->
        while(pred, next, next.(data))
      _ ->
        data
    end
  end

  def positive_non_zero?(i),
    do: i > 0

  def say_hello_once(i) do
    IO.puts("hello")
    i - 1
  end

  def demo1,
    do: while(&positive_non_zero?/1, &say_hello_once/1, 10)

  def demo2 do
    data = {1.01, [1.01, 1.02, 1.04]}

    p = fn {i,p} ->
      i in p
    end

    n = fn {last, p} ->
      i = last + 0.01
      IO.puts(i)
      {i, p}
    end

    while(p, n, data)
  end

end

IO.puts("# demo1")
IO.inspect(Demo.demo1())
IO.puts("# demo2")
IO.inspect(Demo.demo2())
$ elixir demo.exs
# demo1
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
0
# demo2
1.02
1.03
{1.03, [1.01, 1.02, 1.04]}
$

Refactoring: Replace Iteration with Recursion
Refactoring: Replace Recursion with Iteration

Recursion to Iteration Series
Recursion? We don’t need no stinking recursion!

Where Next?

Popular in Questions Top

fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
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
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New

Other popular topics Top

TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
273 38985 115
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
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New

We're in Beta

About us Mission Statement