Предположим, я хочу написать функцию, которая принимает любой ассоциативный оператор ⊕ и добавляет к нему методы, так что я могу заменить любое значение на функцию.Семантика этих дополнительных методов следующая:
- Если оператор затем применяется к любым двум функциям
f
и g
, результатом должна быть функция, которая сначала применяет f
иg
(независимо) к своим аргументам и затем применяет ⊕ к результатам. - Если один аргумент является функцией
f
, а другой - любым нефункциональным значением x
, результатом является функциякоторый сначала применяет f
к своим аргументам, а затем применяет ⊕ к результату и x
.
Я могу выразить это в коде как:
associative!(⊕) = begin
⊕(f::F, y) where F<:Function = (xs...) -> f(xs...) ⊕ y
⊕(x, g::G) where G<:Function = (xs...) -> x ⊕ g(xs...)
⊕(f::F, g::G) where {F<:Function, G<:Function} = (args...) -> f(args...) ⊕ g(args...)
⊕(f::F, y, zs...) where F<:Function = f ⊕ ⊕(y, zs...)
⊕(x, g::G, zs...) where G<:Function = x ⊕ ⊕(g, zs...)
⊕(f::F, g::G, zs...) where {F<:Function, G<:Function} = f ⊕ ⊕(g, zs...)
end
Однако, когдаЯ пытаюсь скомпилировать эту функцию, я получаю следующую ошибку:
ERROR: syntax: cannot add method to function argument ⊕
Я знаю, что могу написать функцию высшего порядка, которая возвращает новую функцию / оператор, основанный надано.Например:
associative(⊞) = begin
let ⊕(x) = x
⊕(x, y) = x ⊞ y
⊕(x, y, zs...) = ⊕(x⊞y, zs...)
associative!(⊕)
⊕
end
end
Если я приведу здесь определение associative!
, тогда associative
прекрасно работает, и я могу написать:
⊕ = associative(+)
⊗ = associative(*)
f(x) = 3⊗x ⊕ 1
f(1) # 4
f(cos)(0) # 4
Но я думал, что это будетПриятно иметь и мутантную версию.Я предполагаю, что переписать associate!
как макрос будет работать, но на самом деле, похоже, нет ничего, что потребовало бы здесь использования макроса.Итак, возможно ли сделать это как функцию более высокого порядка, и если да, то как?