case — конструкция для сопоставления выражения (точнее, его значения) с паттернами, имеющая несколько ветвей (кляуз).
Общий вид оператора case ... end
таков:
case Выражение of
Паттерн1 [when Гарда1] -> ПоследовательностьВыражений1;
Паттерн2 [when Гарда2] -> ПоследовательностьВыражений2;
...
end
Сначала вычисляется Выражение — так получается некий терм. Этот терм сопоставляется по очереди с каждым паттерном. Если паттерн подошёл, идёт проверка по гарде (если гарда есть), если и эта проверка пройдёна, запускается последовательность выражений. Результат последнего выражения и будет результатом работы всего оператора case ... end
.
Этот оператор по своему смыслу и работе очень похож на функцию. Та тоже на вход получает некоторый терм, так же сравнивает терм с паттернами, а потом проверяет по гардам, после чего запускается тело данной кляузы. Отличий фактически только два.
Во-первых, декоративные. Нам не надо куда-то отдельно выносить функцию, не надо давать название функции. case ... end
выполняется здесь и сейчас, в конкретных условиях. Где-то, может быть, другой, похожий, case ... end
, но это значения не имеет.
Во-вторых, case имеет доступ к переменным вокруг себя.
main() ->
A = 1000,
B = 1024,
C = case B of
X -> Z = X-A, X+A
end,
io:format("~p ~p ~n", [C, Z]).
Результат:
2024 24
В этом примере case ... end
смог прочитать переменную A. Он смог бы прочитать и любые другие переменные, находящиеся в данной области видимости. Функция (обычная, не фунтерм) имеет доступ только к тем значениям, которые ей явно передаются в качестве аргумента.
Также он смог к переменной Z привязать значение. И это значение оказалось доступно снаружи case ... end
. Из обычной функции может быть возвращён только один терм.
Таким образом, использование case ... end
чревато непредсказуемостью и побочными эффектами. Лучше проявлять осторожность. Такого рода кляуз X -> Z = X-A, X+A
, где используются переменные помимо Х, стоит избегать. Если надо создавать промежуточные переменные, правильнее будет для этих целей использовать функцию.
Но в целом, конечно, case ... end
очень удобен для ветвления программы. Часто я использую его в конце функций для возвращения значения — в зависимости от обстоятельств.
© Алексей Карманов, 2024.