Como faço para quebrar um loop?
var largest=0
for(i<-999 to 1 by -1) {
for (j<-i to 1 by -1) {
val product=i*j
if (largest>product)
// I want to break out here
else
if(product.toString.equals(product.toString.reverse))
largest=largest max product
}
}
Como transformar aninhados para loops em recursão de cauda?
Do Scala Talk no FOSDEM 2009 http://www.slideshare.net/Odersky/fosdem-2009-1013261 na 22ª página:
Quebre e continue Scala não os possui. Por quê? Eles são um pouco imperativos; melhor usar muitas funções menores Emita como interagir com fechamentos. Eles não são necessários!
Qual a explicação?
scala
for-loop
break
tail-recursion
TiansHUo
fonte
fonte
i
ej
. Se esse código for concluído sem interromper o loop, o resultado é que,906609
ao sair do loop mais cedo, o resultado será90909
que o loop não estará tornando o código "mais eficiente", pois está alterando o resultado.Respostas:
Você tem três (mais ou menos) opções para interromper os loops.
Suponha que você queira somar números até que o total seja maior que 1000. Você tenta
exceto que você deseja parar quando (soma> 1000).
O que fazer? Existem várias opções.
(1a) Use alguma construção que inclua uma condição que você teste.
(aviso - isso depende dos detalhes de como o teste takeWhile e o foreach são intercalados durante a avaliação e provavelmente não devem ser usados na prática!).
(1b) Use recursão de cauda em vez de um loop for, aproveitando a facilidade de escrever um novo método no Scala:
(1c) Volte a usar um loop while
(2) Lance uma exceção.
(2a) No Scala 2.8+, isso já está pré-empacotado no
scala.util.control.Breaks
uso de sintaxe que se parece muito com a sua antiga quebra familiar do C / Java:(3) Coloque o código em um método e use return.
Isso é intencionalmente tornado não muito fácil por pelo menos três razões em que consigo pensar. Primeiro, em grandes blocos de código, é fácil ignorar as instruções "continue" e "break", ou pensar que você está quebrando mais ou menos do que realmente é, ou precisar interromper dois loops que você não pode executar de qualquer maneira facilmente - portanto, o uso padrão, embora útil, tem seus problemas e, portanto, você deve tentar estruturar seu código de maneira diferente. Segundo, Scala tem todos os tipos de aninhamentos que você provavelmente nem percebe; portanto, se você pudesse se libertar, provavelmente ficaria surpreso com a localização do fluxo do código (principalmente nos fechamentos). Terceiro, a maioria dos "loops" de Scala não são realmente loops normais - são chamadas de método que têm seu próprio loop,de maneira irregular, é difícil encontrar uma maneira consistente de saber o que "quebra" e coisas semelhantes devem fazer. Portanto, para ser consistente, a coisa mais sábia a fazer é não ter uma "pausa".
Nota : Existem equivalentes funcionais de todos eles em que você retorna o valor, em
sum
vez de modificá-lo no lugar. Estes são Scala mais idiomáticos. No entanto, a lógica permanece a mesma. (return
torna-sereturn x
, etc.).fonte
breakable
seção ... e todos esses argumentos apenas para evitar o malbreak
, hmm ;-) Você tem que admitir, a vida é irônica.break
] Se parecer com umbreak
e executa como umbreak
, tanto quanto eu estou preocupado é umbreak
.Isso mudou no Scala 2.8, que possui um mecanismo para usar quebras. Agora você pode fazer o seguinte:
fonte
Nunca é uma boa ideia sair do loop for. Se você estiver usando um loop for, significa que você sabe quantas vezes deseja iterar. Use um loop while com 2 condições.
por exemplo
fonte
Para adicionar a resposta de Rex Kerr de outra maneira:
(1c) Você também pode usar uma proteção em seu loop:
fonte
Como ainda não existe
break
no Scala, você pode tentar resolver esse problema usando umareturn
declaração. Portanto, você precisa colocar seu loop interno em uma função; caso contrário, o retorno pulará o loop inteiro.Scala 2.8, no entanto, inclui uma maneira de quebrar
http://www.scala-lang.org/api/rc/scala/util/control/Breaks.html
fonte
use o módulo Break http://www.tutorialspoint.com/scala/scala_break_statement.htm
fonte
Basta usar um loop while:
fonte
Uma abordagem que gera os valores em um intervalo à medida que iteramos, até uma condição de interrupção, em vez de gerar primeiro um intervalo inteiro e depois iterá-lo, usando
Iterator
, (inspirado no uso do @RexKerrStream
)fonte
Aqui está uma versão recursiva da cauda. Comparado com as compreensões, é um pouco enigmático, é certo, mas eu diria que é funcional :)
Como você pode ver, a função tr é a contrapartida das compreensões externas e tr1 da interna. Você é bem-vindo se souber uma maneira de otimizar minha versão.
fonte
Perto da sua solução seria esta:
A iteração j é feita sem um novo escopo, e a geração do produto e a condição são feitas na declaração for (não é uma boa expressão - não encontro uma melhor). A condição é invertida, o que é bastante rápido para o tamanho do problema - talvez você ganhe algo com uma pausa para loops maiores.
String.reverse converte implicitamente em RichString, e é por isso que eu faço duas reversões extras. :) Uma abordagem mais matemática pode ser mais elegante.
fonte
O
breakable
pacote de terceiros é uma alternativa possívelhttps://github.com/erikerlandson/breakable
Código de exemplo:
fonte
Método básico para quebrar o loop, usando a classe Breaks. Declarando o loop como quebrável.
fonte
Simplesmente podemos fazer em Scala é
resultado :
fonte
Ironicamente, a invasão do Scala
scala.util.control.Breaks
é uma exceção:O melhor conselho é: NÃO use break, continue e vá! Na OMI, elas são as mesmas, más práticas e uma fonte maligna de todos os tipos de problemas (e discussões quentes) e, finalmente, "consideradas prejudiciais". Bloco de código estruturado, também neste exemplo as quebras são supérfluas. Nosso Edsger W. Dijkstra † escreveu:
fonte
Eu tenho uma situação como o código abaixo
Estou usando uma java lib e o mecanismo é que o ctx.read lança uma exceção quando não encontra nada. Eu estava preso na situação em que: eu tenho que interromper o loop quando uma exceção foi lançada, mas scala.util.control.Breaks.break usando Exception para interromper o loop, e estava no bloco catch e foi capturado.
Eu tenho uma maneira feia de resolver isso: faça o loop pela primeira vez e obtenha a contagem do comprimento real. e use-o para o segundo loop.
fazer uma pausa no Scala não é tão bom quando você está usando algumas bibliotecas java.
fonte
Eu sou novo no Scala, mas que tal isso para evitar exceções e repetir métodos:
use-o assim:
se você não quer quebrar:
fonte
O uso inteligente do
find
método de coleta fará o truque para você.fonte
fonte
Não sei o quanto o estilo Scala mudou nos últimos 9 anos, mas achei interessante o uso da maioria das respostas existentes
vars
ou a recursão difícil de ler. A chave para sair mais cedo é usar uma coleção lenta para gerar seus possíveis candidatos e, em seguida, verifique a condição separadamente. Para gerar os produtos:Em seguida, encontre o primeiro palíndromo dessa visualização sem gerar todas as combinações:
Para encontrar o maior palíndromo (embora a preguiça não lhe compre muito, porque você precisa verificar a lista inteira):
Seu código original está na verdade verificando o primeiro palíndromo maior que um produto subseqüente, o mesmo que verificando o primeiro palíndromo, exceto em uma condição de limite estranha que eu acho que você não pretendia. Os produtos não estão diminuindo estritamente monotonicamente. Por exemplo,
998*998
é maior que999*997
, mas aparece muito mais tarde nos loops.De qualquer forma, a vantagem da geração preguiçosa e da verificação de condição separadas é que você a escreve da mesma maneira que está usando a lista inteira, mas gera apenas o necessário. Você meio que consegue o melhor dos dois mundos.
fonte