Рассмотрим следующий код:
iex|1 ▶ [:foo, :bar] -- [:foo, :bar]
#⇒ []
Пока все хорошо.Но:
iex|2 ▶ [:foo, :bar] -- [] -- [:foo, :bar]
#⇒ [:foo, :bar]
Более того, речь идет не справа налево:
iex|3 ▶ [:foo, :bar] -- [:foo] -- [:foo, :bar]
#⇒ [:foo, :bar]
iex|4 ▶ IO.inspect([:foo, :bar], label: "1") --
...|4 ▶ IO.inspect([:foo], label: "2") --
...|4 ▶ IO.inspect([:foo, :bar], label: "3")
#⇒ 1: [:foo, :bar]
# 2: [:foo]
# 3: [:foo, :bar]
#⇒ [:foo, :bar]
Я что-то упускаю из виду?Что тут происходит?Не должно быть никакой магии, так как Kernel.--/2
просто делегирует :erlang.--(left, right)
.
Почему последовательные вычитания списков приводят к noop?
FWIW,с круглыми скобками все работает, как и ожидалось:
iex|5 ▶ ([:foo, :bar] -- [:foo]) -- [:foo, :bar]
#⇒ []
Веселее:
iex|6 ▶ [:foo, :bar] -- [:foo] -- []
#⇒ [:bar]
iex|7 ▶ [:foo, :bar] -- [:foo] -- [:foo]
#⇒ [:foo, :bar]
iex|8 ▶ [:foo, :bar] -- [:foo] -- [:bar]
#⇒ [:bar]
Последующие выводы. Сокращение краткой формы как-тоудается следовать правоассоциативной семантике:
Enum.reduce([[:foo, :bar], [:foo], [:foo, :bar]], &Kernel.--/2)
#⇒ [:foo, :bar]
Но полная правильно сформированная семантика с явной функцией не
Enum.reduce(
[[:foo, :bar], [:foo], [:foo, :bar]],
fn e, acc -> acc -- e end
)
#⇒ []