在伞形应用程序中使用捕获操作符-elixir

在伞形应用程序中使用捕获操作符-elixir,elixir,Elixir,我有一个雨伞应用程序, 在一个应用程序(ex:App1)中,我将函数作为参数发送到另一个应用程序(ex:App2)中的不同函数。 我发送的函数如下所示: 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

我有一个雨伞应用程序,
在一个应用程序(ex:App1)中,我将函数作为参数发送到另一个应用程序(ex:App2)中的不同函数。
我发送的函数如下所示:

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,因为Capture操作符假定您将提供函数,如下所示:

&Mod.fun/arity
&local/arity
或者至少可以使用捕获操作符指定一个参数,例如
&Mod.fun(&1)

在这种情况下,你的论点是错误的。 如果没有捕获运算符,并且使用常规的匿名函数生成方法,您将有:

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

因此它适用于
Project.get.Project[:app]
的内容。我不熟悉这个奇特的模块,但它应该在您称之为它的模块中工作。

此示例将抛出CompileError,因为Capture操作符假定您将提供函数,该函数如下所示:

&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"
这里需要注意的两个重要部分是:

  • 在匿名函数中看到打印之前,我们打印了
    我在FOO
    。这意味着该函数在
    Foo
    中执行
  • 我们能够评估
    Bar.baz/0
    ,即使
    Foo
    无法看到该函数(它本身也没有
    baz/0
    函数)。这意味着它在传递到
    Foo.Foo/1
    之前必须经过评估

如果您要这样做,它将在
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"
这里需要注意的两个重要部分是:

  • 在匿名函数中看到打印之前,我们打印了
    我在FOO
    。这意味着该函数在
    Foo
    中执行
  • 我们能够评估
    Bar.baz/0
    ,即使
    Foo
    无法看到该函数(它本身也没有
    baz/0
    函数)。这意味着它在传递到
    Foo.Foo/1
    之前必须经过评估

要控制在其中执行函数的项目,可以使用

通常,在函数之间传递lambda将保留定义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>
iex(10)>lambda=fn->IO.put(“lambda运行在:{inspect(self())}”)结束
#作用
iex(11)>lambda.()
Lambda磨合:#PID
:好的
iex(12)>产卵(λ)
Lambda磨合:#PID
#PID

这可以更改依赖于当前流程字典的任何内容的输出,例如
exto.Repo
,它在事务中存储流程字典中的当前连接。

要控制在其中执行函数的项目,可以使用

通常,在函数之间传递lambda将保留定义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>
iex(10)>lambda=fn->IO.put(“lambda运行在:{inspect(self())}”)结束
#作用
iex(11)>lambda.()
Lambda磨合:#PID
:好的
iex(12)>产卵(λ)
Lambda磨合:#PID
#PID

这可以更改依赖于当前流程字典的任何内容的输出,例如
exto.Repo
,它在事务内部时将当前连接存储在流程字典中。

这可能是打字错误,因为您调用的是
App2.Bar
函数,而不是
App1.Bar
@PatNowak,谢谢,editedIt很可能是打字错误,因为您不是从
App1.Bar
@PatNowak调用
App2.Bar
的函数,谢谢,当我按照您的建议进行编辑时fn->Io.puts(Project.get.Project[:app])end,哪个应用程序将运行?运行此函数的应用程序-App2。当我按照您的建议进行时fn->Io.puts(Project.get.Project[:app])end,哪个应用程序将运行?运行此功能的应用程序-App2。