无限循环与计数器在不老长寿

时间:2017-12-23 15:46:50

标签: functional-programming elixir

我正在学习函数式编程,我想实现类似的东西。

while(true) do
  if(somethingHappensHere) {
    break
  }
  counter++
end
return counter

如何使用elixir以功能方式执行此操作?

谢谢你。

4 个答案:

答案 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条件的示例。

1)如果guard clause中允许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

2)如果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

3)如果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)