Hi, I’m very new to Elixir, I’m struggling with writing loop. i have this simple code in javascript and would like to know how can I write the same in Elixir.
function print() {
for (var p = 990; p > 99; p -= 11) {
console.log('Print');
}
Hi, I’m very new to Elixir, I’m struggling with writing loop. i have this simple code in javascript and would like to know how can I write the same in Elixir.
function print() {
for (var p = 990; p > 99; p -= 11) {
console.log('Print');
}
Elixir is a functional language.
1..9
or 990..99
or 990..99//-11
, for iterating over numbers.990..99
|> Enum.take_every(11)
|> IO.inspect()
Output:
[990, 979, 968, 957, 946, 935, 924, 913, 902, 891, 880, 869, 858, 847, 836, 825,
814, 803, 792, 781, 770, 759, 748, 737, 726, 715, 704, 693, 682, 671, 660, 649,
638, 627, 616, 605, 594, 583, 572, 561, 550, 539, 528, 517, 506, 495, 484, 473,
462, 451, ...]
P.S. Elixir code is similar to writing JavaScript using Ramda.js or Lodash, in case you have used those libraries, you will be able to relate.
P.P.S. I just learnt how to write List Comprehension, that may look like for loop in JavaScript’s for, but shouldn’t be used like that!
for x <- 990..99//-11, do: IO.inspect x
In elixir, as in most other functional languages, we do not write loops using a for
.
Elixir has special form that is often cofused by new users with loops, as its named for
, though it is actually used for comprehensions.
Repeating things is usually done via recursion or comprehensions or the Enum
module.
Depending on your elixir version the following might already do the correct thing:
Enum.each(990..99//-11, fn _ -> IO.puts("Print") end)
Hello and welcome, one quick answer…
Enum.each(990..99//-11, fn _x -> IO.puts("Print") end)
But for some reason, trying to replicate JS code in Elixir is going to be hard.
Your code is imperative with mutation.
Elixir is descriptive and immutable.
You will have to use Functional Programming tools if You want to use Elixir
To highlight some problems with your code…
It would be better to have shown what have you tried.
Bummer. I saw this title and was hoping to have a deep discussion of using custom Collectable implementations in the into
option of a for comprehension.
Others mentioned most of the important aspects about how to write Elixir code and what mistakes to avoid
Now, on how to write the code you requested. I will use reduce because you mentioned accumulator
“JavaScript way”:
print = fn () ->
990..00
|> Enum.reduce(fn x, acc ->
if acc > 99, do: x - 11, else: acc
end)
IO.inspect("Print")
end
Elixir way:
Already answered above
PS: Using var
in JS?
Do tell, I want to learn about Custom stuff!!
You can define your own Collectable
impl and blend that into for
, (or Enum.into
)
Mix.install([{:ecto, ">= 0.0.0"}], consolidate_protocols: false)
defimpl Collectable, for: Ecto.Query do
import Ecto.Query
def into(query) do
collect = fn
query, {:cont, {f, v}} ->
where(query, [], ^f == ^v)
query, :done ->
query
query, :halt ->
:ok
end
{query, collect}
end
end
import Ecto.Query
filter = [{:in_stock, true}, {:on_sale, true}]
q = for {field, val} <- filter, into: from("products"), do: {field, val}
IO.inspect(q)
# => Ecto.Query<from p0 in "products",
# where: ^:in_stock == ^true,
# where: ^:on_sale == ^true>
# this can also just be written as reduce
q = for {f, v} <- filter, reduce: from("products") do
query -> where(query, [], ^f == ^v)
end
IO.inspect(q)
# => Ecto.Query<from p0 in "products",
# where: ^:in_stock == ^true,
# where: ^:on_sale == ^true>
# reduce is probably most interesting when you (ab)use for's pattern matching too
# which can avoid an additional clause to Enum.reduce if your harddrive is low on disk space.
filters = [{:in_stock, true}, {:on_sale, false}]
q = for {f, true} <- filter, reduce: from("products") do
query -> where(query, [], ^f == true)
end
# => Ecto.Query<from p0 in "products",
# where: ^:in_stock == ^true>
I don’t think I’ve actually ever done this in production, probably because I have never needed my own low-level collection type and writing it for “composite” structs seems a bit obtuse vs just manipulating fields. Or maybe I just lack imagination. (Obviously it is quite useful with the built in collections types.)
Anyone have a real-world example?
That’s a verbose way of typing q = Enum.into(filter, from("products"))
I’ve done a custom Collectable implementation that I used to good effect, but not in combination with a for comprehension. I could imagine them used more for algorithmic purposes, such as a GroupingCollector that in a single pass groups things under common map keys, or a SortingCollector that can efficiently sort things without an additional pass.