На многих языках задания являются законными в условиях. Я никогда не понимал причины этого. Зачем вам писать:
if (var1 = var2) {
...
}
вместо:
var1 = var2;
if (var1) {
...
}
На многих языках задания являются законными в условиях. Я никогда не понимал причины этого. Зачем вам писать:
if (var1 = var2) {
...
}
вместо:
var1 = var2;
if (var1) {
...
}
Это более полезно для циклов, чем для операторов.
while( var = GetNext() )
{
...do something with var
}
Что в противном случае нужно было бы записать
var = GetNext();
while( var )
{
...do something
var = GetNext();
}
Это более полезно, если вы вызываете функцию:
if (n = foo())
{
/* foo returned a non-zero value, do something with the return value */
} else {
/* foo returned zero, do something else */
}
Конечно, вы можете просто положить n = foo(); на отдельном утверждении, то if (n), но я думаю, что это выше, это довольно читаемая идиома.
Я нахожу его наиболее полезным в цепочках действий, которые часто включают обнаружение ошибок и т.д.
if ((rc = first_check(arg1, arg2)) != 0)
{
report error based on rc
}
else if ((rc = second_check(arg2, arg3)) != 0)
{
report error based on new rc
}
else if ((rc = third_check(arg3, arg4)) != 0)
{
report error based on new rc
}
else
{
do what you really wanted to do
}
Альтернативой (не используя присвоение в условии) является:
rc = first_check(arg1, arg2);
if (rc != 0)
{
report error based on rc
}
else
{
rc = second_check(arg2, arg3);
if (rc != 0)
{
report error based on new rc
}
else
{
rc = third_check(arg3, arg4);
if (rc != 0)
{
report error based on new rc
}
else
{
do what you really wanted to do
}
}
}
При длительной проверке ошибок альтернатива может выходить из RHS страницы, в то время как версия с условным назначением не делает этого.
Это может быть полезно, если вы вызываете функцию, которая возвращает данные для работы или флаг, чтобы указать на ошибку (или что вы сделали).
Что-то вроде:
while ((c = getchar()) != EOF) {
// process the character
}
// end of file reached...
Лично это идиома, которую я не очень люблю, но иногда альтернатива уродливее.
GCC может помочь вам обнаружить (с -Wall), если вы непреднамеренно попытаетесь использовать назначение как значение истины, если оно рекомендует писать
if ((n = foo())) {
...
}
т.е. используйте дополнительные круглые скобки, чтобы указать, что это действительно то, что вы хотите.
Идиома более полезна, когда вы пишете цикл while вместо инструкции if. Для оператора if вы можете разбить его, как вы описали. Но без этой конструкции вам придется либо повторить:
c = getchar();
while (c != EOF) {
// ...
c = getchar();
}
или используйте структуру "петля и половина":
while (true) {
c = getchar();
if (c == EOF) break;
// ...
}
Я бы предпочел бы форму "петля-и-половина".
В PHP, например, полезно для циклического использования результатов SQL-базы данных:
while ($row = mysql_fetch_assoc($result)) {
// Display row
}
Это выглядит намного лучше, чем:
$row = mysql_fetch_assoc($result);
while ($row) {
// Display row
$row = mysql_fetch_assoc($result);
}
Короткий ответ заключается в том, что Expression-oriented языки программирования позволяют использовать более краткий код. Не заставляйте вас отдельные команды из запросов.
Другим преимуществом является использование gdb. В следующем коде код ошибки не известен, если мы должны сделать один шаг.
while (checkstatus() != -1) {
// process
}
Вместо
while (true) {
int error = checkstatus();
if (error != -1)
// process
else
//fail
}
Теперь в течение одного шага мы можем узнать, каков был код ошибки возврата из checkstatus().
if((var = someFunction())){ //Enclosed in additional pair of brackets to show its intentional
...
Вышеуказанное можно использовать вместо...
var = someFunction();
if(var){
...
Причина такова:
Повышение производительности (иногда)
Малый код (всегда)
Возьмем пример: существует метод someMethod(), а в if вы хотите проверить, является ли возвращаемое значение метода null. Если нет, вы снова будете использовать возвращаемое значение.
If(null != someMethod()){
String s = someMethod();
......
//Use s
}
Это будет мешать производительности, поскольку вы вызываете тот же метод дважды. Вместо этого используйте:
String s;
If(null != (s = someMethod())) {
......
//Use s
}