Guards
Допустимість guards відповідає зафіксованим правилам OTP 29
erl_internal/erl_lint; вона ніколи не виводиться з реєстрації в runtime.
Перевіряється кожен операнд, включно з недосяжними. Guard успішний лише тоді, коли кінцеве
значення — атом true.
Потік керування
,поєднує перевірки по черзі.;починає нову альтернативу післяfalse, небулевого значення або досягнутої семантичної помилки; коли всі альтернативи не вдаються, клауза не зіставляється.- Зв'язування з голови клаузи доступні для читання в кожній альтернативі; guards не створюють зв'язувань.
- Інфраструктурні помилки (OOM, ліміти, володіння) зупиняють виконання й ніколи не переходять до іншої альтернативи.
| Оператор | Семантика |
|---|---|
A andalso B | A має бути булевим; false → false; інакше повертає B як будь-який терм |
A orelse B | A має бути булевим; true → true; інакше повертає B |
and, or, xor | Обидва операнди обчислюються по черзі, обидва булеві |
not A | Булеве заперечення |
true andalso 7 повертає 7 у тілі та не проходить як кінцева перевірка guard;
(true andalso 7) =:= 7 успішне. Досягнута помилка всередині вкладеного виразу
відхиляє всю альтернативу: hd([]) orelse true не проходить, hd([]); true
успішне. У тілах некоректні строгі операнди спричиняють badarg, а некоректний
лівий операнд лінивого оператора спричиняє {badarg, Value}, як в OTP.
Каталог
guards.tsv перелічує всі 81
сигнатуру guards із зафіксованих таблиць guard_bif, new_type_test,
old_type_test, arith_op, bool_op і comp_op, а тест вимагає точної
рівності множин з upstream.
Маніфест аудиту
зіставляє кожну з них із власником у резолвері, пониженні та runtime. Усі 81
реалізовано: self() — це pid процесу, що викликає, node() і node/1 для
pid, посилання чи порту дорівнюють nonode@nohost (вузол один; будь-який інший
аргумент node/1 провалює guard, а в тілі дає badarg). Native records у
guards: is_record/1,2,3 і доступ до полів, як у
native records.
- Перевірки типів:
is_atom,is_integer,is_float,is_number,is_boolean,is_tuple,is_list,is_map,is_binary,is_bitstring,is_function/1,2(funs),is_pid,is_reference(pid і посилання),is_port(порти). is_integer(V, Lo, Hi)спершу перевіряє, що обидві межі є цілими числами (інакшеbadarg), а потім перевіряє належність до включного діапазону; переставлені межі дають false.- Порівняння
==,/=,=:=,=/=,<,=<,>,>=; арифметичні та побітові оператори; запити й перетворення згідно з термами. - Конструктори та оновлення map у guards використовують ті самі служби з коренями, що й тіла.
- Перевірки records: див. терми.
Розв'язання імен
- Некваліфіковані guard BIF враховують локальні визначення, імпорти та
глобальний/вибірковий
no_auto_import.erlang:F(...)іerlang:'op'(...)обходять затінення, але лише для guard BIF та операторів. - Застарілі перевірки (
integer/1,float/1,atom/1,record/2, ...) допустимі лише на верхньому рівні перевірки guard (дужки дозволені). Тамfloat(X)означаєis_float; вкладений або кваліфікованийfloat/1є перетворенням. Застарілийrecord/2ігнорує приховування свого старого імені, але локальнийis_record/2його блокує. - Не дозволено в guards: присвоєння, довільні локальні/віддалені/динамічні
виклики,
++,--,!, funs, comprehensions, керування потоком, оновлення records,record_info/2.
Обмеження оракула
Встановлений OTP 29.1.1 аварійно завершується під час перетворення в SSA для деяких сторонніх сучасних імпортів за застарілими скалярними псевдонімами; Clause явно відхиляє такого неавторизованого власника. Завантажувач OTP також відхиляє guard з величезною літеральною арністю record, хоча lint її приймає; для цього випадку є лише семантичні докази.
Clause