在Elixir中获得错误的功能错误

Tac*_*oat 2 erlang functional-programming elixir phoenix-framework

只是弄乱了elixir结果得到了一个我无法弄清楚的错误.这是我的片段,我为一些api调用实现了一个简单的Parallel map函数.func是进行实际调用的函数,它返回{:ok,result}或{:error,reason},它在不同函数中的映射后处理

本来

def pmap(collection,func,limit \\ 5000) do
    collection
    |> Enum.map(&Task.async(func.(&1)))
    |> Enum.map(&Task.await(&1,limit))
Run Code Online (Sandbox Code Playgroud)

得到错误因此将其更改为可读性

def pmap(collection,func,limit) do
  collection
  |>Enum.map(fn(x) -> Task.async(func.(x)) end)
  |>Enum.map(fn(task) -> Task.await(task,limit) end)
Run Code Online (Sandbox Code Playgroud)

我得到的错误是状态

[error] Task #PID<0.197.0> started from #PID<0.187.0> terminating
** (BadFunctionError) expected a function, got: {:ok,result}
erlang.apply/2
(elixir) lib/task/supervised.ex:85: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:36: Task.Supervised.reply/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Function: &:erlang.apply/2
Run Code Online (Sandbox Code Playgroud)

从我收集的内容来看,假设实际的任务集合元素作为函数传递

所以我修改了函数

    IO.puts "PMAP BEGUN"
    tasks = collection
        |> Enum.map(fn(x) -> Task.async(func.(x)) end)
    answer = Enum.map(tasks,fn(task) -> Task.await(task,limit) end)
    IO.puts "PMAP DONE"
    answer
Run Code Online (Sandbox Code Playgroud)

IO.puts用于调试.所以我猜错误发生在第二个地图上,因为永远不会显示PMAP DONE.我仍然有同样的错误.

这到底出了什么问题?我几乎逐字逐句地编写了相同的函数并且它有效.

Paw*_*zak 6

您遇到的问题在线发生:

  |> Enum.map(fn(x) -> Task.async(func.(x)) end)
Run Code Online (Sandbox Code Playgroud)

要使它工作,你需要用匿名函数包装函数执行,如:

  |> Enum.map(fn(x) -> Task.async(fn -> func.(x) end) end)
Run Code Online (Sandbox Code Playgroud)

这是因为如果你运行func.(x)它会评估,并且评估的结果将被传递给Task.async/1,当你用函数包装时,它将由它Task来执行.

提示在错误消息中指示:

** (BadFunctionError) expected a function, got: {:ok,result}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!