На многих языках задания являются законными в условиях. Я никогда не понимал причины этого. Зачем вам писать:
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
}