Когда предпочитать `и` над 'и также' в защитных тестах
Мне любопытно, почему запятая <, > является ярлыком для and
, а не andalso
в тестах защиты.
Поскольку я назвал бы себя "родным C", я не вижу недостатков булевой оценки короткого замыкания.
Я скомпилировал некоторый тестовый код, используя флаг to_core
, чтобы узнать, какой код действительно создан. Используя запятую, я вижу значение левой руки, а правое и значение оцениваются, и оба и. С andalso
у вас есть блок-блок в блоке case и нет вызова erlang:and/2
.
Я не тестировал тесты, но, полагаю, вариант andalso
является более быстрым.
Ответы
Ответ 1
Вникать в прошлое:
-
Изначально в стражах были только теги ,
, которые были оценены слева направо, пока их не было больше, и защита сработала или тест не прошел, и защита в целом потерпела неудачу. Позже ;
был добавлен, чтобы позволить чередующимся охранникам в том же предложении. Если охранники оценивают обе стороны ,
перед тестированием, то кто-то ошибся на этом пути. Пример @Kay, похоже, подразумевает, что они действительно идут слева направо, как они должны.
-
Булевы операторы разрешались гораздо позже в охранниках.
-
and
, вместе с or
, xor
и not
, является булевым оператором и не предназначен для управления. Они все строги и сначала оценивают свои аргументы, как арифметические операторы +
, -
, *
и '/'. Существуют также строгие булевы операторы в C.
-
Операторы управления короткого замыкания andalso
и orelse
были добавлены позже, чтобы упростить некоторый код. Как вы сказали, компилятор расширяет их до вложенных выражений case
, поэтому при их использовании нет увеличения производительности, просто удобство и ясность кода. Это объясняет полученный вами код.
-
N.B. в стражах есть тесты, а не выражения. Существует тонкая разница, что означает, что при использовании and
и andalso
эквивалентно ,
использование orelse
не эквивалентно ;
. Это остается другим вопросом. Подсказка: все дело об ошибке.
Таким образом, оба and
и andalso
имеют свое место.
Ответ 2
Адам Линдбергс ссылка верна. Использование запятой генерирует лучший код луча, чем использование andalso. Я скомпилировал следующий код, используя флаг + to_asm:
a(A,B) ->
case ok of
_ when A, B -> true;
_ -> false
end.
aa(A,B) ->
case ok of
_ when A andalso B -> true;
_ -> false
end.
который генерирует
{function, a, 2, 2}.
{label,1}.
{func_info,{atom,andAndAndalso},{atom,a},2}.
{label,2}.
{test,is_eq_exact,{f,3},[{x,0},{atom,true}]}.
{test,is_eq_exact,{f,3},[{x,1},{atom,true}]}.
{move,{atom,true},{x,0}}.
return.
{label,3}.
{move,{atom,false},{x,0}}.
return.
{function, aa, 2, 5}.
{label,4}.
{func_info,{atom,andAndAndalso},{atom,aa},2}.
{label,5}.
{test,is_atom,{f,7},[{x,0}]}.
{select_val,{x,0},{f,7},{list,[{atom,true},{f,6},{atom,false},{f,9}]}}.
{label,6}.
{move,{x,1},{x,2}}.
{jump,{f,8}}.
{label,7}.
{move,{x,0},{x,2}}.
{label,8}.
{test,is_eq_exact,{f,9},[{x,2},{atom,true}]}.
{move,{atom,true},{x,0}}.
return.
{label,9}.
{move,{atom,false},{x,0}}.
return.
Я только посмотрел, что генерируется с флагом + to_core, но, очевидно, есть шаг оптимизации между to_core и to_asm.
Ответ 3
Это историческая причина. and
был реализован до andalso
, который был введен в Erlang 5.1 (единственная ссылка, которую я могу найти сейчас, - EEP-17). Охранники не были изменены из-за обратной совместимости.
Ответ 4
Булевы операторы " и" и " или" всегда оценивают аргументы на обеих сторонах оператора. Если вам нужна функциональность операторов C && и || (где 2-й аргумент оценивается только при необходимости.. например, если мы хотим, чтобы evalue "true orelse false", как только истина окажется первой аргументацией, второй аргумент не будет оцениваться, если не используется " или" ). " и также" и " орал".