Как следующий код Java "продолжить" переводит на Scala?
for (String stock : allStocks) {
Quote quote = getQuote(...);
if (null == quoteLast) {
continue;
}
Price price = quote.getPrice();
if (null == price) {
continue;
}
}
Мне не обязательно нужен перевод строки за строкой, но я ищу способ "Scala" для решения этой проблемы.
Ответы
Ответ 1
Вам не нужно продолжать или прерывать или что-то в этом роде в таких случаях: параметры и для понимания делают трюк очень красиво,
val stocksWithPrices =
for {
stock <- allStocks
quote <- Option(getQuote(...))
price <- Option(quote.getPrice())
} yield (stock, quote, price);
Ответ 2
Как правило, вы пытаетесь избежать этих ситуаций, чтобы начать с фильтрации, прежде чем начать:
val goodStocks = allStocks.view.
map(stock => (stock, stock.getQuote)).filter(_._2 != null).
map { case (stock, quote) => (stock,quote, quote.getPrice) }.filter(_._3 != null)
(в этом примере показано, как вы несете частичные результаты, если они вам понадобятся). Я использовал представление, чтобы результаты были вычислены по мере необходимости, а не создавали кучу новых коллекций на каждом шаге.
Собственно, у вас, вероятно, есть кавычки и такие параметры возврата - посмотрите на StackOverflow для примеров того, как использовать их вместо нулевых возвращаемых значений.
Но, во всяком случае, если такая вещь не работает так хорошо (например, потому что вы генерируете слишком много промежуточных результатов, которые вам нужно сохранить, или вы полагаетесь на обновление изменяемых переменных и хотите сохранить шаблон оценки просто, чтобы вы знали, что происходит когда), и вы не можете представить себе проблему другим, возможно, более надежным способом, тогда вы можете
import scala.util.control.Breaks._
for (stock <- allStocks) {
breakable {
val quote = getQuote(...)
if (quoteLast eq null) break;
...
}
}
Конструкция breakable
указывает, к каким перерывам вам следует отнести. Если вы ставите breakable вне цикла for, он работает как стандартный разрыв в стиле Java. Если вы положили его внутрь, он действует как continue
.
Конечно, если у вас очень небольшое количество условий, вам не нужно продолжать вообще; просто используйте else if-statement.
Ответ 3
Ваша структура управления здесь может отображаться очень идиоматически в следующем цикле for
, и ваш код демонстрирует тип фильтрации, для которого был разработан цикл Scala for
.
for {stock <- allStocks.view
quote = getQuote(...)
if quoteLast != null
price = quote.getPrice
if null != price
}{
// whatever comes after all of the null tests
}
Кстати, Scala автоматически удалит это в код из решения Rex Kerr
val goodStocks = allStocks.view.
map(stock => (stock, stock.getQuote)).filter(_._2 != null).
map { case (stock, quote) => (stock,quote, quote.getPrice) }.filter(_._3 != null)
Это решение, вероятно, вообще не работает для всех типов более сложных потоков, которые могут использовать continue
, но он затрагивает множество общих.
Ответ 4
Если фокус действительно находится на continue
, а не на обработке null
, просто определите внутренний метод (часть обработки null
- это другая идиома в scala):
def handleStock(stock: String): Unit {
val quote = getQuote(...)
if (null == quoteLast) {
return
}
val price = quote.getPrice();
if (null == price) {
return
}
}
for (stock <- allStocks) {
handleStock(stock)
}
Ответ 5
Самый простой способ - вставить пропущенный код в if
с обратным смыслом в то, что у вас есть.
См. http://www.scala-lang.org/node/257