在一个雨伞应用程序中使用捕获操作符 - 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
我的问题是:
没有该功能在实际执行App1
或App2
(其中它被定义)?
答
这个例子将抛出CompileError,因为捕捉操作假定您将提供的功能,这将是这样的:
&Mod.fun/arity
&local/arity
,或者至少要指定一个参数为使用也捕捉运营商如。 &Mod.fun(&1)
。
在这种情况下,你的观点是错误的。 没有捕捉操作和使用让你不得不有匿名函数的常规方式:
fn -> Io.puts(Project.get.project[:app]) end
所以它会为Project.get.project[:app]
内容合作。我不熟悉那个奇特的模块,但它应该在你称之为的模块中工作。
答
如果你是做这样的事情,这将是在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字典中进行连接。
由于您不是从App1.Bar调用'App2.Bar'的函数,所以可能会出现错字。 – PatNowak
@PatNowak,谢谢,编辑 – fay