Почему в Эликсире допустимо x = x +1?

Все, что я читал об Эликсире, говорит о том, что присваивание следует рассматривать как сопоставление с образцом. Если да, то почему x = x + 1 работает в Эликсире? Не существует значения х, для которого х = х + 1.

Потому что Эликсир полностью упускает суть. Вместо этого используйте Erlang везде, где это возможно. Гораздо меньше путаницы.

zxq9 29.01.2021 02:39
Введение в одну из самых важных концепций в React - функциональное программирование
Введение в одну из самых важных концепций в React - функциональное программирование
React разработан с использованием концепции функционального программирования, поэтому понимание функционального программирования важно для изучения...
Фото ️🔁 Radek Jedynak 🔃 on ️🔁 Unsplash 🔃
Фото ️🔁 Radek Jedynak 🔃 on ️🔁 Unsplash 🔃
Что такое Java 8 Streams API? Java 8 Stream API
5
1
430
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Во время сопоставления с образцом ценности справа от совпадения равны назначенный их совпадающему переменные слева:

iex(1)> {x, y} = {1, 2}
{1, 2}
iex(2)> x
1
iex(3)> y
2

С правой стороны используются значения переменных до совпадения. Слева установлены переменные.

Вы также можете заставить левую сторону использовать значение переменной с помощью ^ контактный оператор:

iex(4)> x = 1
1
iex(5)> ^x = x + 1
** (MatchError) no match of right hand side value: 2

Это не удается, потому что это эквивалентно 1 = 1 + 1, что является условием отказа, которое вы ожидали.

Ответ принят как подходящий

Everything I've read about Elixir says that assignment should be thought of as pattern matching.

В Elixir =является вызывает оператор сопоставления с образцом, но он работает не так, как оператор сопоставления с образцом в Erlang. Это потому, что переменные в Эликсире не являются одиночными присваиваниями, как в Эрланге. Вот как работает Erlang:

~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3  (abort with ^G)

1> X = 15.
15

2> X = 100.
** exception error: no match of right hand side value 100

3> X.
15

4> 

Следовательно, в Erlang это не работает:

4> X = X + 1.
** exception error: no match of right hand side value 16

С единичным присваиванием в Erlang все довольно просто: поскольку у X уже есть значение, строка X = X + 1 не может быть попыткой присвоить X новое значение, поэтому эта строка является попыткой сопоставления с образцом (15 = 15 + 1), которая всегда терпит неудачу.

С другой стороны, в Эликсире переменные не имеют одинарного присваивания:

Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> x = 15
15

iex(2)> x = 100
100

iex(3)> x
100

iex(4)> 

Тот факт, что переменные не являются одиночными присваиваниями в Эликсире, означает, что Эликсиру нужно сделать выбор, когда вы пишете:

x = 10
x = x + 1  #or even x = 15

Вариант 1) Следует ли интерпретировать вторую строку как присвоение x?
Вариант 2. Следует ли интерпретировать вторую строку как попытку сопоставления с образцом (т. е. 10 = 11)?

Эликсир идет с Вариантом 1. Это означает, что на самом деле выполнить сопоставление шаблона с так называемым оператором сопоставления шаблонов в Эликсире сложнее: вы должны использовать оператор булавки (^) в сочетании с оператором сопоставления (=):

x = 10
^x = x + 1  

Теперь вторая линия всегда будет терпеть неудачу. Существует также трюк, который будет работать в некоторых ситуациях, если вы хотите выполнить сопоставление с образцом без использования оператора вывода:

x = 10
12 = x

Во второй строке вы помещаете переменную справа. Я думаю, что правило можно сформулировать так: в правой части оператора сопоставления с образцом (=) переменные всегда оцениваются, т. е. заменяются их значениями. В левой части переменные всегда присваиваются, если только не используется оператор закрепления, в этом случае закрепленная переменная заменяется ее текущим значением, а затем шаблон сопоставляется с правой стороной. В результате, вероятно, правильнее будет называть оператор Эликсира = гибридным оператором присваивания/сопоставления с образцом.

Вы можете представить, что x = x + 1 переписывается компилятором во что-то вроде x2 = x1 + 1.

Это очень близко к тому, как это работает. Это не просто порядковый номер, как я использовал здесь, но концепция та же. Переменные, видимые BEAM, неизменяемы, и на этом уровне не происходит повторного связывания.

В программах на Erlang вы повсюду найдете код, похожий на X2 = X1 + 1. У обоих подходов есть недостатки. Хосе Валим сделал сознательный выбор, разрешив повторное связывание переменных, когда разрабатывал Эликсир, и он написал сообщение в блоге, в котором сравнил два подхода и различные ошибки, с которыми вы рискуете:

http://blog.plataformatec.com.br/2016/01/comparing-elixir-and-erlang-variables/

Другие вопросы по теме