在一个雨伞应用程序中使用捕获操作符 - elixir

问题描述:

我有一个雨伞应用程序,
它在一个应用程序(例如:App1)中发送一个函数作为参数位于另一个应用程序中的另一个函数(例如:App2 )。
我送的功能是这样的:在一个雨伞应用程序中使用捕获操作符 - elixir

defmodule App1.Bar do 
    def bar_bar(fun) do 
    fun.() 
    end 
end 

defmodule App2.Foo do 
    def foo_foo do 
    App1.Bar.bar_bar(&Io.puts(Project.get.project[:app])) 
    end 
end 

我的问题是:
没有该功能在实际执行App1App2(其中它被定义)?

+0

由于您不是从App1.Bar调用'App2.Bar'的函数,所以可能会出现错字。 – PatNowak

+0

@PatNowak,谢谢,编辑 – fay

这个例子将抛出CompileError,因为捕捉操作假定您将提供的功能,这将是这样的:

&Mod.fun/arity 
&local/arity 

,或者至少要指定一个参数为使用也捕捉运营商如。 &Mod.fun(&1)

在这种情况下,你的观点是错误的。 没有捕捉操作和使用让你不得不有匿名函数的常规方式:

fn -> Io.puts(Project.get.project[:app]) end 

所以它会为Project.get.project[:app]内容合作。我不熟悉那个奇特的模块,但它应该在你称之为的模块中工作。

+0

当我这样做你建议fn - > Io.puts(Project.get.project [:app])结束,这将运行的应用程序? – fay

+0

运行此功能的应用程序 - App2。 – PatNowak

如果你是做这样的事情,这将是App1执行,但它会在App2评估

让我们看看这实际上是什么意思。假设我们有以下几个模块:

defmodule Foo do 
    def foo(fun) do 
    IO.puts "I AM IN FOO" 
    fun.() 
    end 
end 
defmodule Bar do 
    def bar(), do: Foo.foo(fn -> IO.inspect baz() end) 
    defp baz(), do: "baz" 
end 

iex(1)> Bar.bar() 
I AM IN FOO 
"baz" 
"baz" 

的两个重要组成部分,这里要注意的:

  • 我们印刷I AM IN FOO之前,我们看到在我们的匿名功能的打印。这意味着该功能在Foo中执行。
  • 我们能够评估Bar.baz/0,即使Foo无法看到该功能(它也没有自己的baz/0功能)。这意味着它必须在被传递给Foo.foo/1之前进行过评估。

要控制的功能被中执行的项目,则可以使用Mix.Project.in_project/4

Mix.Project.in_project :my_app, "/path/to/my_app", fn module -> 
    "Mixfile is: #{inspect module}" 
end 
#=> "Mixfile is: MyApp.Mixfile" 

在功能之间一般通过lambda表达式将保留从拉姆达被定义在词法作用域。

然而传递过程之间的lambda将导致self()评估为不同的值:

iex(10)> lambda = fn -> IO.puts("Lambda running in: #{inspect(self())}") end 
#Function<20.52032458/0 in :erl_eval.expr/5> 

iex(11)> lambda.() 
Lambda running in: #PID<0.80.0> 
:ok 

iex(12)> spawn(lambda) 
Lambda running in: #PID<0.96.0> 
#PID<0.96.0> 

这可以改变的任何依赖于当前过程字典的输出,如Ecto.Repo存储该当前在事务处理中的Process字典中进行连接。