Рекурсия и анонимные функции в эликсире
Я пытаюсь определить анонимную функцию для создания точечного продукта, я могу без проблем создать код как частную функцию, но я борюсь с анонимным синтаксисом функции.
Я знаю, что могу реализовать это по-другому, но я пытаюсь понять, как определить анонимные функции с совпадением шаблонов и рекурсией.
Это моя текущая реализация
dot = fn
[i|input],[w|weights], acc -> dot.(input,weights,i*w+acc)
[],[bias],acc -> acc + bias
end
И я получаю эту ошибку при компиляции:
function dot/0 undefined
Любые подсказки? Это просто невозможно?
Ответы
Ответ 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