Подтвердить что ты не робот

Когда предпочитать `и` над 'и также' в защитных тестах

Мне любопытно, почему запятая <, > является ярлыком для and, а не andalso в тестах защиты.

Поскольку я назвал бы себя "родным C", я не вижу недостатков булевой оценки короткого замыкания.

Я скомпилировал некоторый тестовый код, используя флаг to_core, чтобы узнать, какой код действительно создан. Используя запятую, я вижу значение левой руки, а правое и значение оцениваются, и оба и. С andalso у вас есть блок-блок в блоке case и нет вызова erlang:and/2.

Я не тестировал тесты, но, полагаю, вариант andalso является более быстрым.

4b9b3361

Ответ 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", как только истина окажется первой аргументацией, второй аргумент не будет оцениваться, если не используется " или" ). " и также" и " орал".