Ядро .-- / 2 странное поведение - PullRequest
0 голосов
/ 04 февраля 2019

Рассмотрим следующий код:

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
)
#⇒ []

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

При Enum.reduce([[:foo, :bar], [:foo], [:foo, :bar]], fn e, acc -> acc -- e end) у вас не возникнут те же проблемы, что и с [:foo, :bar] -- [:foo] -- [:foo, :bar], потому что вы будете работать над каждым элементом, а не над всеми ними одновременно.

Когда начнется accв [], поэтому с каждым элементом у вас будет:

# 1 => [] - [: foo,: bar] = []

# 2 => []- [: foo] = []

# 3 => [] - [: foo,: bar] = []

Таким образом, в конце у вас будет пустой список.

0 голосов
/ 04 февраля 2019

++ и -- являются правоассоциативными операциями .Ваш исходный код:

[:foo, :bar] -- [:foo] -- [:foo, :bar]

Фактически оценивается как

[:foo, :bar] -- ([:foo] -- [:foo, :bar])

Когда вы берете то, что в скобках: вы удаляете список элементов из [:foo], а список удаляетесодержит исходный список ([:foo]), таким образом, оценивается как пустой список [].

Затем вы удаляете этот пустой список из крайнего левого списка:

[:foo, :bar] -- []

, что оставляет вас срезультат [:foo, :bar].

...