case

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.