Знайте как всъщност работи операторът за равенство

Това е едно от нещата, които обичам в Elixir; това е една от онези много мощни функции, които използвам всеки ден и които ми липсват, когато използвам Python или други езици за програмиране.

Операторът за присвояване “=” е оператор за еквивалентност. В Elixir правим променлива равна на стойност и обратно. Нека да видим пример: присвояване на променливата x на стойността на „здравей“.

Така можем да направим оценка на стойността с променливата, така че да върне първоначалната стойност.

Когато оценяваме променливата със стойност, различна от „hello“, това ще ни даде грешка MatchError. Единственият възможен начин да работи е, ако променливата е от лявата страна на операцията. Това обаче презаписва оригиналната ни променлива.

Деструктуриране на структури от данни чрез съпоставяне на шаблони

По-рано говорихме за няколко структури от данни, кортежи. Казахме, че са подобни на списъците, но се съхраняват по различен начин в паметта. Типът на структурата е много важен, когато говорим за декомпозиция на данни с Pattern Matching. Ще го видим след малко. Първо, нека видим пример за деструктуриране на кортеж.

Ако имаме три елемента в нашия кортеж, можем да инициализираме променлива за всеки от тези елементи по много прост начин:

Така в x имаме atom :hello, а в y atom :world и т.н.

Това работи, като съпоставя броя на променливите с броя на стойностите. Ако имаме по-малко стойности от променливите, ще получим грешка MatchError.

Не можем да присвояваме променливи по този начин, когато типът структура е различен, например сравняване на кортежи със списък.

Много пъти във Phoenix имаме, в резултат на операции, кортеж, където първата стойност е атом от type :ok (или :error), а втората стойност е резултатът (или причината за грешката), и тези атоми имат за съвпадение от двете страни на оператора =.

За деструктуриране на списъци можем да извлечем първия елемент (или последните елементи) по подобен, много прост начин: присвояване на променлива, наречена head на първия елемент, след това поставяне на оператора | и поставяне на променлива там, където останалата част от елементи от списъка ще бъдат.

Можем да разрушим няколко елемента, не само първия. Нека видим пример, в който извличаме първите два елемента:

Празен списък не може да бъде присвоен на две променливи, защото няма съвпадащи елементи.

И това е същата причина, поради която функцията hd/1 (или tl/1) не работи с празен списък. Връщане на грешка от тип ArgumentError в случай на функции или MatchError, както в предишния случай.

Конкатенация на списък със съпоставяне на шаблони

Да кажем, че имаме списък, към който искаме да добавим елемент в началото. Това, което можем да направим, е да използваме оператора ++ между списъците. Можем обаче да използваме и Pattern Matching за това.

Или, както казах, използвайте оператора ++. Въпреки това ще трябва да поставим нашия елемент в нов списък.

Оператор Pin ^

Променливите в Elixir могат да бъдат преназначавани или презаписани. Понякога това не е това, което искаме; понякога това, което искаме, е да направим Pattern Matching. Нека го видим по-ясно с примера в началото на тази публикация.

Ако искаме да видим дали x е еквивалентно на друга стойност, ще трябва да използваме оператора pin. Това е така, за да може да бъде съпоставен вместо преназначен.

Това е много полезно, когато вече имаме инициализирана променлива и искаме да знаем дали резултатът от операция има тази стойност, за да присвоим нова променлива на останалата част от операцията. Ето един пример:

Тъй като има съвпадение, сега имаме в нашата променлива x низа „това е резултат от друга операция“. Ако няма съвпадение, получаваме грешка от тип MatchError и на нашата променлива x не се присвоява нищо.

Това се случва, защото сравняваме :yes_it_is с :nope атоми, но те не са еднакви.

Неизползвани променливи

Често не се интересуваме от запазване на резултата от операция в променлива. Въпреки това, поради броя на елементите, които резултатът връща, трябва да поставим променлива, така че съпоставянето на шаблони да работи правилно.

За това използваме _, което представлява стойност, която ще бъде игнорирана в шаблона. Нека да видим пример с предишния код.

Ако не искаме да използваме низа, който ни дава дясната страна на присвояването, все още трябва да поставим променлива, за да може Pattern Matching да работи. Следното не работи:

Затова решихме да го поставим, както следва:

Заключение

Както можете да видите, Pattern Matching е много елегантен инструмент за извличане на информация. Осигурява гъвкавост и според мен е много по-бързо да се работи по този начин. Ако познавате JS, със сигурност ще сте запознати с този начин за деклариране на променливи.

В следващата публикация ще видим различните контролни структури в Elixir и как те са свързани със съпоставянето на шаблони.

Ето линк към първата част от тази серия.

Препратки