【问题标题】:Elixir: Is there any benefit of using & operator to get an anonymous function out of a named functionElixir:使用 & 运算符从命名函数中获取匿名函数有什么好处
【发布时间】:2019-04-10 18:29:09
【问题描述】:

所以我正在阅读这本书,并且在某些时候它指出:

& 函数捕获运算符还有第二种形式。你可以给 它是现有函数的名称和参数(参数数量), 它会返回一个调用它的匿名函数。

但我不明白为什么有人要这样做。知道可以将命名函数和未命名函数都绑定到变量,如果你愿意的话,可以从中得到什么好处。

【问题讨论】:

    标签: elixir operators anonymous-function


    【解决方案1】:

    拥有一些简单的功能是很常见的,比如

    Enum.map(list, fn(element) -> element.id end)
    

    或者只是

    Enum.map(list, &(&1.id))
    

    通过一些练习,第二个比第一个更容易阅读

    关于你的问题,你也可以用同样的方式调用一个命名函数

    Enum.map(list, &Integer.to_string/1)
    

    另一种方法是使用fn将函数传递给枚举

    Enum.map(list, fn(number) -> Integer.to_string(number) end)
    

    此外,捕获的变体更易于阅读。

    【讨论】:

      【解决方案2】:

      这本书不正确。 &MyModule.my_function/0 确实 not 返回“调用给定函数的匿名函数” - 它返回引用命名函数的函数对象。要获取匿名函数,您可以使用 fn -> MyModule.my_function() end

      当您在运行时重新加载模块时,这变得很重要:匿名函数是创建它的模块的一部分,并且由于给定模块的两个版本仅保存在虚拟机中(“当前”和“旧" 版本),您最终可能会得到一个无法再调用的函数。

      让我们从这个模块开始:

      defmodule MyModule do
        def the_real_function() do
          2
        end
      
        def anonymous_function() do
          fn -> __MODULE__.the_real_function() end
        end
      
        def named_function() do
          &__MODULE__.the_real_function/0
        end
      end
      

      它包含我们真正感兴趣的函数,以及两个返回引用真实函数的函数的函数——一个带有匿名函数,一个带有命名函数对象。

      让我们加载模块,获取两个函数对象,并检查我们是否可以调用它们:

      iex(1)> c "my_module.ex"
      [MyModule]
      iex(2)> f_anon = MyModule.anonymous_function()
      #Function<0.62651516/0 in MyModule.anonymous_function/0>
      iex(3)> f_named = MyModule.named_function()
      &MyModule.the_real_function/0
      iex(4)> f_anon.()
      2
      iex(5)> f_named.()
      2
      

      到目前为止一切顺利。现在,假设我们需要更新模块,以便函数返回 3。我们编辑模块并重新加载它:

      iex(6)> c "my_module.ex"
      warning: redefining module MyModule (current version defined in memory)
        my_module.ex:1
      
      [MyModule]
      iex(7)> f_anon.()
      3
      iex(8)> f_named.()
      3
      

      我们的函数引用仍然有效 - 很好。假设我们需要再次更新模块,返回 4:

      iex(9)> c "my_module.ex"
      warning: redefining module MyModule (current version defined in memory)
        my_module.ex:1
      
      [MyModule]
      iex(10)> f_anon.()
      ** (BadFunctionError) expected a function, got: #Function<0.62651516/0 in MyModule>
      
      iex(10)> f_named.()
      4
      

      现在匿名函数坏了!那是因为我们得到了两个模块版本的引用,因此这个匿名函数的代码不再保存在 VM 中。命名函数引用仍然有效,因为它只是引用具有给定模块、名称和数量的函数。

      【讨论】:

        猜你喜欢
        • 2017-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-03
        相关资源
        最近更新 更多