Почему x = x +1 действителен в Elixir? - PullRequest
0 голосов
/ 23 февраля 2019

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

Ответы [ 3 ]

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

Все, что я читал об Elixir, говорит о том, что назначение следует рассматривать как сопоставление с образцом.

В Elixir = это , называемое сопоставлением с образцомоператор, но он не работает так же, как оператор сопоставления с образцом в Erlang.Это потому, что в 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), которая всегда будет неудачной.

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

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)> 

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

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

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

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

x = 10
^x = x + 1  

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

x = 10
12 = x

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

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

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

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

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

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

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

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

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

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

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

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

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

...