37

我正在尝试定义一个匿名函数来做一个点积,我可以将它编码为一个私有函数而没有任何问题,但我正在努力使用匿名函数语法。我知道我可以以不同的方式实现这一点,但我试图了解如何使用模式匹配和递归来定义匿名函数。这是我目前的实现

dot = fn
  [i|input],[w|weights], acc -> dot.(input,weights,i*w+acc)
  [],[bias],acc -> acc + bias
end

我在编译时收到此错误:

function dot/0 undefined

有什么提示吗?这是不可能的吗?

4

5 回答 5

40

Elixir 中的匿名函数不可能重复出现。

Erlang 17(目前是一个候选版本)为 Erlang 添加了这种可能性,我们计划很快利用它。现在,最好的方法是定义一个模块函数并传递它:

def neural_bias([i|input],[w|weights], acc) do
  neural(input,weights,i*w+acc)
end

def neural_bias([], [bias], acc) do
  acc + bias
end

接着:

&neural_bias/3
于 2014-02-24T09:17:53.003 回答
35

不太正式但仍然可以接受的方法是:

factorial = fn
  (0,_) -> 1
  (1,_) -> 1
  (n, fun) -> n * fun.(n - 1, fun)
end

你用它来称呼它factorial.(6, factorial) # 720

于 2014-09-20T14:28:13.437 回答
12

这是一个固定的 (Y) 组合器:

fix = fn f -> 
    (fn z ->
        z.(z)
    end).(fn x -> 
        f.(fn y -> (x.(x)).(y) end)
    end)
end

以下是你如何使用它:

factorial = fn factorial ->
    fn
        0 -> 0
        1 -> 1
        number -> number * factorial.(number - 1)
    end
end

fix.(factorial).(6) # 720

仅适用于使用 1 个参数递归的函数。Elixir 没有可变参数。要支持多个参数,您需要添加比单个参数更多的参数,y例如:f.(fn a,b -> (x.(x)).(a,b) end)

于 2014-09-14T03:56:31.020 回答
2

您可以定义一个名为 的模块函数fix,然后使用它来定义dot(以及任何其他递归匿名函数):

defmodule A do
    def fix(f, x) do
      f.(fn(x) -> fix(f, x) end, x)
    end

    def fix2(f, x, y) do
      f.(fn(x, y) -> fix2(f, x, y) end, x, y)
    end
end

dot = fn(x, y) ->
    A.fix2(fn
          dot, [i|input],[w|weights], acc -> dot.(input,weights,i*w+acc)
          dot, [],[bias],acc -> acc + bias
    end, x, y)
end
于 2014-02-24T09:28:19.457 回答
0

或者,您可以将您的函数传递给Stream.cycle以创建“无限循环通过给定可枚举的流”。并将其传送到执行无限流函数的 Enum.each 调用中。

test = spawn fn -> [fn -> receive do: (x -> IO.puts x * 2) end] |> Stream.cycle() |> Enum.each(fn f -> f.() end) end 
#PID<0.161.0>
iex(24)> send test, 1 
1 
2 
iex(25)> send test, 1 
1 
2 
iex(26)> Process.alive?(test) 
true
于 2022-02-10T18:59:47.867 回答