Есть ли причина предпочитать '&&' над '&' в 'if' заявлениях, кроме короткого замыкания?

Да, я знаю, было несколько вопросов (например, этот относительно использования & vs. && в R, но я не нашел тот, который конкретно отвечает на мой вопрос.

Как я понимаю различия,

  • & делает элементное, векторное сравнение, как и другие арифметические операции. Поэтому он возвращает логический вектор с длиной > 1, если оба аргумента имеют длину > 1.
  • && сравнивает первые элементы обоих векторов и всегда возвращает результат длины 1. Кроме того, он выполняет короткое замыкание: cond1 && cond2 && cond3 && ... оценивает только cond2, если cond1 есть TRUE и т.д., Это позволяет использовать такие вещи, как if(exists("is.R") && is.function(is.R) && is.R()) и, в частности, означает, что в некоторых случаях строго необходимо использовать &&.

Кроме того, if выдает предупреждение

условие имеет длину > 1, и будет использоваться только первый элемент

если его условие имеет более одного элемента.

Судя по этим предварительным комментариям, я бы счел более безопасным предпочесть & - && во всех операторах if, где короткое замыкание не требуется.

Если во время вычислений что-то пошло не так, и у меня случайно есть вектор в одном из аргументов &, я получаю предупреждение, что хорошо. Если нет, все будет хорошо.

Если, с другой стороны, я использовал &&, и в моих вычислениях что-то пошло не так, и один из аргументов && - это вектор, я не получаю предупреждение. Это плохо. Если по какой-то причине я действительно хочу сравнить первые элементы двух векторов, я бы сказал, что сделать это намного чище, чем явно, а не явно.

Обратите внимание, что это противоречит тому, что, по-видимому, является общим соглашением между программистами R и противоречит рекомендациям R docs. (1)

Следовательно, мой вопрос: Существуют ли какие-либо причины, кроме короткого замыкания, которые делают && предпочтительнее & в выражениях if?


(1) Цитирование help(&&):

'&' и '& &' указать логические И и '|' и '||' указывать логическое ИЛИ. Более короткая форма выполняет поэлементные сравнения в почти так же, как и арифметические операторы. Более длинная форма оценивает слева направо, исследуя только первый элемент каждого вектор. Оценка продолжается только до тех пор, пока не будет определен результат. Более длинная форма подходит для программирования потока управления и обычно предпочтительнее в предложениях "if".

Ответ 1

Короткий ответ: Да, другой символ делает смысл более понятным для читателя.

Спасибо за этот интересный вопрос! Если я могу подвести итог, кажется, что это вопрос о данном разделе моего ответа к вопросу, который вы связали,

... вы хотите использовать длинные формы только тогда, когда вы уверены, что векторы - одна. Вы должны быть абсолютно уверены в своих векторах являются только длиной 1, например, в тех случаях, когда они являются функциями, которые return only length 1 booleans. Вы хотите использовать короткие формы, если векторы - длина, возможно, > 1. Поэтому, если вы не совсем уверены, вы следует либо сначала проверить, либо использовать короткую форму, а затем использовать все и любой, чтобы уменьшить его до длины один для использования в операциях потока управления, как если.

Я слышу ваш вопрос (учитывая комментарии) следующим образом: Но & и && будут делать то же самое, если входы имеют длину один, поэтому, кроме короткого замыкания, почему предпочитаете &&? Возможно, предпочтительнее &, потому что, если они не длинны одна, if предоставит мне предупреждение, помогая мне быть еще более уверенным, что входы являются длиной один.

Во-первых, я согласен с комментарием @James, что вы можете "переоценить ценность получения предупреждения"; если он не длинный, тем безопаснее будет справляться с этим должным образом, а не просто пахать вперед. Вы могли бы сделать случай, когда && должен выдать ошибку, если они не являются одной длиной и, возможно, хорошим случаем; Я не знаю, почему он делает то, что он делает. Но, не возвращаясь вовремя, самое лучшее, что мы можем сделать сейчас, это проверить, действительно ли входы подходят для вашего использования.

Учитывая, что вы проверили, чтобы убедиться, что ваши входы подходят, я по-прежнему рекомендую &&, потому что он семантически напоминает мне, как читателю, что я должен быть уверен, что входы являются скалярами (длина одна). Я так привык думать, что это напоминание полезно для меня. Он следует принципу, что разные операции должны иметь разные символы, и для меня операция, предназначенная для использования на скалярах, отличается от вексеризованной операции, которая требует другого символа.

(Не начинать пламенную войну (надеюсь), но это также почему я предпочитаю <- - =, один для назначения переменных, один для настройки параметров для функций. Хотя в глубине души это одно и то же, на практике он достаточно различен, чтобы сделать разные символы полезными для меня как читателя.)

Ответ 2

Нет, использование && не дает никаких преимуществ, кроме короткого замыкания.

Однако короткое замыкание очень предпочтительнее для потока управления, настолько, что оно должно быть по умолчанию. Операторы if не должны брать векторизованные аргументы - для чего ifelse. Если вы передаете логический вектор в if, вы обычно заключаете его с одним логическим значением, используя any или all для оценки.

Основные преимущества короткого замыкания заключаются в том, чтобы избежать длительных или неудачных шагов (например, интернет-соединений - хотя они должны рассматриваться через try):

#avoiding lengthy calculations
system.time(if(FALSE & {Sys.sleep(2);TRUE}) print("Hello"))
   user  system elapsed 
   0.00    0.00    1.99 
system.time(if(FALSE && {Sys.sleep(2);TRUE}) print("Hello"))
   user  system elapsed 
      0       0       0 

#avoiding errors
if(FALSE & {stop("Connection Failed");TRUE}) print("Success") else print("Condition not met")
Error: Connection Failed
if(FALSE && {stop("Connection Failed");TRUE}) print("Success") else print("Condition not met")
[1] "Condition not met"

Понятно, что для того, чтобы воспользоваться этими функциями, вам нужно заранее знать, какие шаги занимают самые длинные или подвержены ошибкам и соответствующим образом строят логический оператор.