web-dev-qa-db-ja.com

Elixirの再帰関数と無名関数

ドット積を実行するために無名関数を定義しようとしています。これをプライベート関数として問題なくコーディングできますが、無名関数の構文に苦労しています。これを別の方法で実装できることはわかっていますが、パターンマッチングと再帰を使用して無名関数を定義する方法を理解しようとしています。これは私の現在の実装です

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

そして、コンパイル時にこのエラーが発生します:

function dot/0 undefined

ヒントはありますか?これは不可能ですか?

34
Batou99

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
38
José Valim

あまり正式ではありませんが、それでも受け入れられるアプローチは次のとおりです。

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

factorial.(6, factorial) # 720で呼び出します

30
hamiltop

固定(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には可変引数がありません。複数の引数をサポートするには、f.(fn a,b -> (x.(x)).(a,b) end)のように単一のyよりも多くの引数を追加する必要があります。

9
CMCDragonkai

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
2
Ramon Snir