Ваш код выдает ошибку в основном из-за того, что вы пытаетесь решить свою проблему с помощью неверного алгоритма. Тот факт, что JLS не допускает использование троичного в качестве условия в для цикла , также не помогает - но главная проблема в том, что вы упускаете правильное решение задачи.
Давайте начнем с общего утверждения, prematureOptimization == sqrt(sum(evil))
- сначала вы должны рассмотреть , что вы хотите сделать, а не , как это сделать или , почему код не работает.
Шаг i должен быть равен 1, если n равно> = 0, в противном случае -1
( примечание: если n является инвариантом (и он здесь) с использованием, например, abs (n) или n < 0 в условии, это плохая практика, хотя большинство компиляторов будет пытаться вычленить инвариант из цикла, обычно следует просто используйте временную переменную для хранения результата и вместо этого используйте результат в сравнении)
Итак, код под рукой должен быть:
void doSomething( int n ) {
if ( n >= 0 )
for( int i = 0; i < n; i++ )
f( i, n );
else
for( int i = 0; i > n; i-- )
f( i, n );
}
Факторинг из инвариантов и разделение отдельных ветвей кода - основные методы, используемые для повышения эффективности алгоритмов (не преждевременная оптимизация , обратите внимание); нет более быстрого и чистого способа сделать это. Некоторые могут возразить, что это случай разматывания петли - это очень хорошо было бы , если бы не тот факт, что эти две петли не должны быть намотаны вместе в первую очередь .. . [1 125]
Другое дело: третья операция в для цикла всегда была обычным оператором; давайте попробуем угадать , почему следующий код не компилируется?
0 <= n ? (i++) : (i--); // error: not a statement
... может быть, потому что следующий код тоже не скомпилируется?
0 <= n ? i : i; // error: not a statement
... и это по той же причине, что приведенный ниже код не будет работать и в Java?
i; // error: not a statement
Ваш ответ: ternary - это не утверждение - ternary просто возвращает значение и значение не является оператором ( по крайней мере в Java ); i++
и i--
разрешены в троичной форме только потому, что они возвращают значение , но они также вызывают побочные эффекты здесь.
На самом деле я совершенно не согласен с Дэниелом. Я думаю, что неравный синтаксис никогда не должен использоваться . Если ваш метод представлен как API, и вы беспокоитесь о случайном возврате неправильного типа, добавьте явную аннотацию типа:
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello!")
123
}
}
Неравный синтаксис короче и может выглядеть «чище», но я думаю, что он просто добавляет возможность путаницы. Иногда я забывал добавить знак равенства и полагал, что мой метод возвращает значение, хотя на самом деле он возвращал Unit. Поскольку синтаксисы неравенства и равенства с предполагаемым типом визуально схожи, эту проблему легко упустить.
Хотя это требует от меня немного больше работы, я предпочитаю явные аннотации типов, когда они имеют значение (а именно , открытые интерфейсы).
ОБНОВЛЕНИЕ: начиная с Scala-2.10, использование знака равенства является предпочтительным. Старый ответ:
Методы, возвращающие Unit
, должны всегда использовать синтаксис «не равно». Это позволяет избежать возможных ошибок при переносе реализации в API. Например, вы могли случайно сделать что-то вроде этого:
object HelloWorld {
def main(args: Array[String]) = {
println("Hello!")
123
}
}
Тривиальный пример, конечно, но вы можете видеть, как это может быть проблемой. Поскольку последнее выражение не возвращает Unit
, сам метод будет иметь тип возврата, отличный от Unit
. Это доступно в общедоступном API и может вызвать другие проблемы в будущем. С синтаксисом non-equals, не имеет значения, какое последнее выражение является последним, Scala фиксирует возвращаемый тип как Unit
.
Он также очищает два символа. : -) Я также склонен думать, что синтаксис "не равно" упрощает чтение кода. Более очевидно, что рассматриваемый метод возвращает Unit
, а не какое-то полезное значение.
В соответствующем примечании существует аналогичный синтаксис для абстрактных методов:
trait Foo {
def bar(s: String)
}
Метод bar
имеет подпись String => Unit
. Scala делает это, когда вы опускаете аннотацию типа для абстрактного члена. Еще раз, это чище и (я думаю) легче читать.
Вы должны использовать знак равенства в объявлениях вызовов, за исключением определений, возвращающих Unit.
В последнем случае вы можете отказаться от знака равенства . Однако этот синтаксис может быть устаревшим, поэтому его лучше избегать. Использование знака равенства и объявление типа возврата всегда будет работать.
Одно: представьте последний оператор метода, который должен возвращать Unit, не возвращает Unit. Тогда использование неравного синтаксиса очень удобно, я надеюсь, что это не будет устаревшим, поскольку я вижу несколько вариантов его использования