I'm studying functional programming and I want to implement something like this.
while(true) do
if(somethingHappensHere) {
break
}
counter++
end
return counter
How can I do this in functional way using elixir?
Thanks for this.
While in most functional programming languages one would use a recursion for this task, Elixir particularly provides the way to do this without using an explicit recursion call: Enum.reduce_while/3
:
Enum.reduce_while(1..100, 0, fn i, acc ->
if condition, do: {:halt, acc}, else: {:cont, acc + i}
end)
For lazy evaluation one would use Stream.reduce_while/3
.
To make it infinite, one might use one of infinite generators, provided by Stream
module, like Stream.iterate/2
:
Stream.iterate(0, &(&1+1)) |> Enum.reduce_while(0, fn i, acc ->
if i > 6, do: {:halt, acc}, else: {:cont, acc + 1}
end)
#⇒ 7
For the sake of recursion, this is how the recursive solution might be implemented in Elixir:
defmodule M do
def checker, do: & &1 <= 0
def factorial(v, acc \\ 1) do
if checker().(v), do: acc, else: factorial(v - 1, v * acc)
end
end
M.factorial 6
#⇒ 720
Not sure about elixir specifically, but you can achieve this using recursion:
function myFunction(int counter)
{
if (condition) {
return counter
}
return myFunction(counter + 1)
}
This essentially sets up a function that can infinitely recurse (call itself), each time passing in the next counter value.
By having the recursive call as the last thing the function does, this is known as tail-call recursion which elixir supports (as per: Does Elixir infinite recursion ever overflow the stack?)
This can then be used as such:
int counterValue = myFunction(0)
With the function only returning once the condition is true.
You could also make this more generic by having the function take another function that returns true or false (i.e. performs the conditional check).
As I said, unfortunately I'm not aware of the syntax of elixir, but I'm sure you'll be able to bridge that gap.
An example of something in Elixir syntax:
defmodule SOQuestion do
def test(counter) do
if (something_happens_here?()), do: counter, else: test(counter+1)
end
def something_happens_here?() do
true
end
end
And it would be invoked like this:
SOQuestion.test(0)
A couple of notes on this:
1.) It's a code fragment. Obviously it's tough to be very complete given the broad nature of your question.
2.) something_happens_here?
being a predicate it would normally be named ending with a question mark.
3.) If something_happens_here?
were defined in a different module, then the call would be if (Module.something_happens_here?())
4.) I've obviously coded something_happens_here?
to simply return true
unconditionally. In real code, of course, you'd want to pass some argument to something_happens_here?
and act on that to determine which boolean to return.
Given all that I totally agree with @mudasowba--this sort of thing is usually better handled with one of the higher order functions built into the language. It's less error prone and often much easier for others to read too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With