Подтвердить что ты не робот

Рекурсия и анонимные функции в эликсире

Я пытаюсь определить анонимную функцию для создания точечного продукта, я могу без проблем создать код как частную функцию, но я борюсь с анонимным синтаксисом функции. Я знаю, что могу реализовать это по-другому, но я пытаюсь понять, как определить анонимные функции с совпадением шаблонов и рекурсией. Это моя текущая реализация

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

И я получаю эту ошибку при компиляции:

function dot/0 undefined

Любые подсказки? Это просто невозможно?

4b9b3361

Ответ 1

Невозможно повторить анонимные функции в 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

Ответ 2

Менее формальный, но все же приемлемый подход:

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

Вы вызываете его с помощью factorial.(6, factorial) # 720

Ответ 3

Здесь фиксированный (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 аргументом. Эликсир не имеет переменных аргументов. Чтобы поддерживать несколько аргументов, вам нужно добавить больше аргументов, чем один y: f.(fn a,b -> (x.(x)).(a,b) end).

Ответ 4

Вы можете определить модульную функцию с именем 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