Всегда ли у условного побочные эффекты? [закрыто]

10

Я беру курс по промежуточным структурам данных в качестве предварительного условия для поступления в программу CS MS в университете, о котором все в Америке слышали. Одна строчка кода, написанная в классе, привлекла мое внимание:

if (a > 33 | b++ < 54) {...}

Это не пройдет проверку кода на моем рабочем месте. Если вы напишете такой код в интервью, это будет серьезным ударом по вам. (В дополнение к условности с побочными эффектами, это умный за счет ясности.)

На самом деле, я никогда не видел условия с побочными эффектами, и Googling тоже мало что показывает. Еще один студент остался после урока, чтобы спросить об этом тоже, так что я не единственный, кто думал, что это странно. Но профессор был непреклонен в том, что это приемлемый код, и что он напишет что-то подобное на работе. (Его работа в FT в качестве руководителя SWE в компании, о которой вы все слышали.)

Я не могу представить себе мир, в котором эта строка кода была бы приемлемой, не говоря уже о желательности. Я ошибаюсь? Это нормально? Как насчет более общего случая: условия с побочными эффектами? Это когда-нибудь нормально?

rianjs
источник
7
Эта строка должна быть взята с орбиты. Дважды за хорошую меру.
Blrfl
8
Гнида: одиночная труба (вертикальная черта) является побитовой или в большинстве языков, а не логическим «или». Это не короткое замыкание, если левая сторона верна. Так как у этого условия есть побочные эффекты на правой стороне, это имеет особенно большое значение в результате.
Джонатан Юнис
2
Существуют идиомы, используемые на разных языках, которые попадают в эту категорию, но поскольку они «хорошо известны» или «нормальны», не вызывают проблем. Строка в вопросе, кажется, не попадает в категорию идиоматического использования, поэтому я бы ее избегал.
Джейди
2
@JonathanEunice, да, некоторые люди были озадачены оценкой короткого замыкания. Не опечатка с моей стороны.
rianjs
5
Посмотри на светлую сторону. Теперь вы знаете еще одну компанию, где не хотите брать интервью.
Джон Р. Штром

Ответы:

23

Есть один полуобусловленный побочный эффект, который я могу считать вполне приемлемым:while(iter.MoveNext())

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

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

Telastyn
источник
Это была просто пустая строка в методе во время урока. Это не было предназначено, чтобы сделать что-нибудь полезное.
rianjs
4
Эквивалентно, while(v = *p++)сканирование в стиле C / C ++ через массив с нулевым символом в конце (например, строка C) довольно распространено и широко распространено.
Фил Миллер
3
Я часто считал условные циклы формы while(c = input.read() != '\n')достаточно идиоматичными.
1
Может быть несколько распространенных приемлемых идиом, но ясно, что «быть умным за счет ясности» попадает в лагерь НИКОГДА.
Джулия Хейворд
Я полностью забыл об iter.MoveNext (). Совершенно разумный случай для условного побочного эффекта. Спасибо!
rianjs
8

В моем мире чтение из памяти может рассматриваться как побочный эффект (например, отображение ввода-вывода в память).

Теперь рассмотрим следующее:

    while( ( *memory_mapped_device_status_register & READY_FLAG) == 0) {
       // Wait
    }

И сравните с:

    status = *memory_mapped_device_status_register;
    while( ( status & READY_FLAG) == 0) {
        // Wait
        status = *memory_mapped_device_status_register;
    }

Избегал ли побочный эффект (чтение) в условиях читабельности условия; или он просто дублирует код и добавляет беспорядок?

Недопустимо, чтобы условие имело побочные эффекты (если это делает код менее читабельным), и также нормально, чтобы условие имело побочные эффекты (если это делает код более читабельным). Ключевым фактором является «читабельность». Все остальное - это правила, созданные дураками в ошибочной попытке улучшить читаемость (хотя часто имеют обратный эффект).

Brendan
источник
3

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

Тем не менее, каковы примеры оправданных побочных эффектов в if? Например, предположим, что вы обязаны по закону регистрировать все и любой доступ к свойству Pобъекта Eдля целей аудита. (Представьте, что вы работаете на заводе по обогащению урана, и существует очень строгий юридический контроль над тем, что вашему коду разрешено делать и как он должен это делать.) Тогда любой, ifкоторый проверяет это свойство, вызовет побочный эффект журнал аудита расширяется.

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

Чем больше эти смягчающие обстоятельства исчезают, тем более странной становится конструкция. Если конкретный тип цикла (например if((c = getc()) == 'x') { quit(); }, хорошо известен и принят языковым сообществом, то это гораздо меньше проблем, чем когда вы его изобретаете самопроизвольно и т. Д. Ваша примерная строка не соответствует этому стандарту, но я могу себе представить, очень, очень более ужасные, которые я даже не буду печатать, они такие ужасные.

Килиан Фот
источник
2

Хотя это действительно вонючий код, его преимущество в том, что он проще (и, возможно, быстрее, если у вас нет хорошего оптимизирующего компилятора), чем его эквивалент if (a > 33 | b < 54) {b++; ...} else b++;

но, конечно, можно оптимизировать его следующим образом (но будьте осторожны! в случае переполнения это поведение будет другим): b++; if (a > 33 | b < 53) {...}

Франки
источник