我正在学习函数式编程,我想实现类似的东西。
while(true) do
if(somethingHappensHere) {
break
}
counter++
end
return counter
如何使用elixir以功能方式执行此操作?
谢谢你。
答案 0 :(得分:6)
虽然在大多数函数式编程语言中,人们会使用递归来完成此任务,但Elixir特别提供了在不使用显式递归调用的情况下执行此操作的方法:Enum.reduce_while/3
:
Enum.reduce_while(1..100, 0, fn i, acc ->
if condition, do: {:halt, acc}, else: {:cont, acc + i}
end)
对于懒惰评估,可以使用Stream.reduce_while/3
。
要使其无限,可以使用由Stream
模块提供的无限生成器之一,如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
为了递归,这就是在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
答案 1 :(得分:1)
不确定elixir,但你可以使用递归实现这一点:
function myFunction(int counter)
{
if (condition) {
return counter
}
return myFunction(counter + 1)
}
这实质上设置了一个函数,每次传递下一个计数器值时都可以无限递归(调用自身)。
通过将递归调用作为函数执行的最后一项操作,这称为elixir支持的尾调用递归(根据:Does Elixir infinite recursion ever overflow the stack?)
然后可以这样使用:
int counterValue = myFunction(0)
只有在条件为真时才返回该函数。
你也可以通过使用另一个函数返回true或false(即执行条件检查)来使这更通用。
正如我所说,遗憾的是我并不知道灵药的语法,但我确信你能够弥合这一差距。
答案 2 :(得分:1)
Elixir语法中的一个例子:
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
它会像这样调用:
SOQuestion.test(0)
关于此的几点说明:
1。)它是一个代码片段。显然,鉴于你的问题的广泛性,很难做到非常完整。
2。)something_happens_here?
是一个谓词,它通常被命名为以问号结尾。
3。)如果something_happens_here?
在另一个模块中定义,那么呼叫将是if (Module.something_happens_here?())
4。)我明显编码something_happens_here?
只是无条件地返回true
。当然,在实际代码中,您希望将一些参数传递给something_happens_here?
并对其进行操作以确定要返回的布尔值。
鉴于我完全同意@ mudasowba的所有内容 - 通常使用语言中内置的高阶函数之一来处理这种事情。它不容易出错,而且其他人也更容易阅读。
答案 3 :(得分:0)
如上所述,您可以使用许多内置函数,例如Enum.reduce_while/3
。但是,有时使用简单的递归同样简单(或有趣)。
我将制作一些通用示例,并使用bar(foo)
作为somethingHappensHere
条件的示例。
bar(foo)
:defmodule Counter do
def count do
count(foo, 0)
end
defp count(foo, count) when bar(foo), do: count
defp count(foo, count), do: count(foo, count + 1)
end
bar(foo)
是一个返回布尔值的函数:defmodule Counter do
def count(foo) do
count(foo, 0)
end
defp count(foo, count) do
if bar(foo) do
count
else
count(foo, count + 1)
end
end
end
bar(foo)
返回布尔值以外的其他内容,则可以进行模式匹配,例如:defmodule Counter do
def count(foo) do
count(foo, 0)
end
defp count(foo, count) do
case bar(foo) do
{:ok, baz} -> count
{:error, _} -> count(foo, count + 1)
end
end
end
调用模块和功能:
Counter.count(foo)