Зачем использовать код короткого замыкания? - PullRequest
5 голосов
/ 16 ноября 2009

Смежные вопросы : Преимущества использования оценки короткого замыкания , Почему язык НЕ использует оценку короткого замыкания? , Может кто-нибудь объяснить эта строка кода, пожалуйста? (Операторы логики и назначения)

Есть вопросы о преимуществах языка, использующего код короткого замыкания, но мне интересно, каковы преимущества для программиста? Просто ли это может сделать код немного более кратким? Или есть причины производительности?

Я не спрашиваю о ситуациях, когда в любом случае нужно оценивать две сущности, например:

if($user->auth() AND $model->valid()){
  $model->save();
}

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

Это также имеет (для меня) очевидную цель:

if(is_string($userid) AND strlen($userid) > 10){
  //do something
};

Потому что было бы неразумно вызывать strlen() с нестроковым значением.

Что меня интересует, так это использование кода короткого замыкания, когда он не влияет на другие операторы. Например, со страницы индекса по умолчанию Zend-приложения:

defined('APPLICATION_PATH')
 || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

Это могло бы быть:

if(!defined('APPLICATION_PATH')){
  define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
}

Или даже как одно утверждение:

if(!defined('APPLICATION_PATH'))
  define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

Так зачем использовать код короткого замыкания? Просто для фактора «крутизны» использования логических операторов вместо структур управления? Чтобы закрепить вложенные if заявления? Потому что это быстрее?

Ответы [ 9 ]

4 голосов
/ 16 ноября 2009

Для программистов преимущество менее подробного синтаксиса перед другим более подробным синтаксисом может быть:

  • меньше, чтобы напечатать, поэтому более высокая эффективность кодирования
  • меньше для чтения, поэтому удобнее в обслуживании.

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

Часто, когда вы видите конкретные конструкции на одном языке, вы хотите, чтобы язык, который вы используете, могли иметь, но даже не обязательно осознавали это раньше. Несколько примеров из головы:

  • анонимные внутренние классы в Java вместо передачи указателя на функцию (намного больше строк кода).
  • в Ruby, операторе || =, для вычисления выражения и присвоения ему, если оно оценивается как false или равно нулю. Конечно, вы можете добиться того же с помощью 3 строк кода, но почему?
  • и многие другие ...
4 голосов
/ 16 ноября 2009

Я не знаю PHP, и я никогда не видел короткого замыкания, используемого вне условия if или while в семействе языков C, но в Perl очень идиоматично говорить:

open my $filehandle, '<', 'filename' or die "Couldn't open file: $!";

Одним из преимуществ наличия всего этого в одном операторе является объявление переменной. В противном случае вам придется сказать:

my $filehandle;
unless (open $filehandle, '<', 'filename') {
    die "Couldn't open file: $!";
}

Трудно утверждать, что второй в этом случае чище. И это было бы более по-прежнему на языке, который не имеет unless

4 голосов
/ 16 ноября 2009

Используйте это, чтобы запутать людей!

2 голосов
/ 17 ноября 2009

Операторы короткого замыкания могут быть полезны в двух важных обстоятельствах, которые еще не были упомянуты:

Дело 1 . Предположим, у вас есть указатель, который может быть или не быть NULL, и вы хотели проверить, что это не NULL и что он указал на 0. Тем не менее, вы должны не разыменовывать указатель, если он равен NULL. Без операторов короткого замыкания вы должны были бы сделать это:

if (a != NULL) {
  if (*a != 0) {
    ⋮
  }
}

Однако операторы короткого замыкания позволяют записать это более компактно:

if (a != NULL && *a != 0) {
  ⋮
}

при определенном знании, что *a не будет не оцениваться, если a равно NULL.

Дело 2 . Если вы хотите установить для переменной не ложное значение, возвращаемое одной из серии функций, вы можете просто сделать:

my $file = $user_filename ||
           find_file_in_user_path() ||
           find_file_in_system_path() ||
           $default_filename;

Устанавливает значение от $file до $user_filename, если оно присутствует, или результат find_file_in_user_path(), если это правда, или ... и так далее. Возможно, это встречается в Perl чаще, чем в C, но я видел это в C.

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

2 голосов
/ 16 ноября 2009

Я думаю, что ваш пример для фактора крутости. Нет причин писать такой код.

РЕДАКТИРОВАТЬ: У меня нет проблем с этим по идиоматическим причинам. Если все остальные, кто использует язык, используют оценку короткого замыкания для создания сущностей, похожих на операторы, которые все понимают, то вы тоже должны это делать. Однако мой опыт показывает, что подобный код редко пишется на языках семейства C; правильной формой является просто использование оператора if, как обычно, который отделяет условный (который, по-видимому, не имеет побочных эффектов) от вызова функции, которым управляет условный (который, по-видимому, имеет много побочных эффектов).

1 голос
/ 16 ноября 2009

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

0 голосов
/ 14 декабря 2011

Подумайте об этом так, если у вас есть утверждение типа

if( A AND B )

Скорее всего, если A вернет FALSE, вы когда-либо захотите оценить B только в редких особых случаях. По этой причине НЕ следует использовать оценку коротких замыканий.

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

0 голосов
/ 17 ноября 2009

Правда на самом деле производительность. Короткое замыкание используется в компиляторах для устранения экономии мертвого кода на размер файла и скорость выполнения. Во время выполнения короткое замыкание не выполняет оставшееся предложение в логическом выражении, если их результат не влияет на ответ, что ускоряет оценку формулы. Я изо всех сил пытаюсь вспомнить пример. * 1001 например *

А И В И С

В этой формуле есть два термина, оцениваемых слева направо.

если значение AND b равно FALSE, следующее выражение AND c может быть либо FALSE AND TRUE, либо FALSE AND FALSE. Оба оценивают в FALSE независимо от значения c. Следовательно, компилятор не включает AND c в скомпилированном формате, что приводит к короткому замыканию кода.

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

0 голосов
/ 16 ноября 2009

Что если бы у вас была дорогая функция (с точки зрения производительности), которая в правой части возвращала логическое значение, которое вы хотели вызывать, только если другое условие было истинным (или ложным)? В этом случае короткое замыкание экономит много циклов ЦП. Это делает код более кратким из-за меньшего количества вложенных операторов if. Итак, по всем причинам, которые вы указали в конце вашего вопроса.

...