用外部.ex文件编写的Elixir匿名函数无法与交互式shell一起运行

时间:2018-07-10 07:01:14

标签: elixir anonymous-function first-class-functions

我可以直接在交互式shell中编写一个匿名函数,如下所示。

iex> total_bottles_milk = fn total -> total * 2 end  
iex> total_bottles_milk.(2)

但是,如果我编写一个外部文件并在交互式Shell中运行,它将显示“编译错误”。

我的文件名和目录路径是lib / expense.ex

下面是我的代码

defmodule Expense do

    total_bread_slices = fn total -> (total * 10) / 100 end
    total_bottles_milk = fn total -> total * 2 end
    total_cakes = fn total -> total * 15 end

    def total_expense(bread_slices, bottles_of_milk, cakes) do
        total_bread_slices.(bread_slices) + total_bottles_milk.(bottles_of_milk) + total_cakes.(cakes)
    end

end

当我进入文件夹路径并运行iex -S mix以运行我的Expense模块时,终端会显示编译错误。
我只是想知道我是否可以直接在交互式外壳程序中运行匿名函数,而不是从外部源进行编译。我想写我作为一等公民的职能。如果有办法,我该怎么办?

4 个答案:

答案 0 :(得分:3)

您无法在长生不老药中创建这样的“变量”(请参见下面的String configName = 'AaConfig' Class config = this.getClass().getClassLoader().loadClass(configName) EDIT 1)。您看到的错误是正常的。

您可以将匿名函数放入已命名的函数中,然后从那里调用它们,从而得到相同的结果:

Edit 2

这样,您将调用命名函数,该函数将返回匿名函数,然后将参数传递给该匿名函数。

编辑1

您不能创建类似于INSIDE模块的变量。这在iex中有效,因为它是一个交互式环境。但是,defmodule Expense do def total_expense(bread_slices, bottles_of_milk, cakes) do total_bread_slices().(bread_slices) + total_bottles_milk().(bottles_of_milk) + total_cakes().(cakes) end defp total_bread_slices, do: fn total -> (total * 10) / 100 end defp total_bottles_milk, do: fn total -> total * 2 end defp total_cakes, do: fn total -> total * 15 end end 语法在elixir模块中的函数外部无效。

编辑2 感谢@Dogbert的更正。您实际上可以在模块内部和函数外部创建变量,但是不能在x = y内部使用它们。

答案 1 :(得分:0)

感谢@Abdullah Esmail,我可以这样编写函数

defmodule Expense do

    def total_bread_slices do
        fn total -> (total * 10) / 100 end
    end 

    def total_bottles_milk do
        fn total -> total * 2 end
    end 

    def total_cakes do
        fn total -> total * 15 end
    end 

    def total_expense(bread_slices, bottles_of_milk, no_of_cakes) do

        bread = total_bread_slices()
        milk = total_bottles_milk()
        cakes = total_cakes()

        bread.(bread_slices) + milk.(bottles_of_milk) + cakes.(no_of_cakes)
    end

end

答案 2 :(得分:0)

感谢@Dogbert,如果我要将函数用作值,这是另一种方法。

首先,我定义一个命名函数,然后使用Elixir的函数捕获运算符&,可以更轻松地将命名函数用作值。

通过这种方式,使用&运算符捕获对函数的引用,并使用=运算符绑定到变量,我可以将命名函数绑定到变量。

defmodule Expense do

    defp total_bread_slices(total) do
        (total * 10) / 100
    end 

    defp total_bottles_milk(total) do
        total * 2 
    end 

    defp total_cakes(total) do
        total * 15 
    end 

    def total_expense(bread_slices, bottles_of_milk, no_of_cakes) do

        bread = &total_bread_slices/1
        milk = &total_bottles_milk/1
        cakes = &total_cakes/1

        bread.(bread_slices) + milk.(bottles_of_milk) + cakes.(no_of_cakes)

    end

end

答案 3 :(得分:0)

在第二版Elixir In Action书中的示例运行过程中,我遇到了同样的问题。为了避免在iex中重新键入lambda函数示例,我将它们保存在文件中。我试图将它们加载到iex中,例如:

iex solutions/ch05.ex

但是当我调用lambda函数时:

a_lambda.("something")

我在iex中遇到编译错误。

现在,我将Lambda代码从文件直接复制/粘贴到Iex,并且可以正常工作。