Controle de Fluxo
Controle de Ramificação (Condicionais)
O controle de ramificação permite que o programa execute blocos de código com base em condições. Existem três tipos:
Condicional Simples
Executa um bloco de código se a expressão condicional for verdaedira.
if (condicao) {
// Bloco de código a ser executado
}
Condicional Composta
Executa um bloco de código se a condição for verdadeira e outro bloco se for falsa.
if (condicao) {
// Executado se a condição for verdadeira
} else {
// Executado se a condição for falsa
}
Condicional Múltipla
Permite verificar uma série de condições em sequência.
if (condicao1) {
// Executado se condicao1 for verdadeira
} else if (condicao2) {
// Executado se condicao2 for verdadeira
} else {
// Executado se nenhuma das condições anteriores for verdadeira
}
Retorno de Expressões Condicionais
Em Scala, as expressões if-else retornam um valor. O valor retornado é o resultado da última expressão avaliada no bloco executado.
package controlefluxo
import scala.io.StdIn
object ExemploCondicionais {
def main(args: Array[String]): Unit = {
print("Digite sua idade: ")
val idade: Int = StdIn.readInt()
// Condicional Simples
if (idade > 18) {
println("Você é maior de idade.")
}
println("--------------------")
// Condicional Composta
if (idade >= 18) {
println("Adulto.")
} else {
println("Menor de idade.")
}
// Condicional Múltipla
val faixaEtaria = if (idade <= 6) {
"Infância"
} else if (idade <= 18) {
"Adolescência"
} else if (idade < 40) {
"Jovem"
} else {
"Idoso"
}
println(s"Faixa etária: $faixaEtaria")
// Retorno de valor de uma expressão condicional
val genero: Char = 'F'
val resultadoGenero = if (genero == 'M') {
println('M')
"Masculino"
} else if (genero == 'F') {
println('F')
"Feminino"
} else {
println("Indefinido")
"Outro"
}
println(s"Gênero: $resultadoGenero")
}
}
Condicionais Aninhadas
É possível aninhar estruturas condicionais dentro de outras.
Laços de Repetição for (For Comprehensions)
Scala oferece recursos poderosos para laços for, conhecidos como "for comprehensions" ou "for expressions".
Iteração sobre Ranges (inclusivo to)
Itera sobre um intervalo numérico de forma inclusiva.
for (i <- 1 to 5) {
println(s"Iteração: $i")
}
Iteração sobre Ranges (exclusivo until)
Itera sobre um intervalo numérico de forma exclusiva no limite superior.
for (i <- 1 until 5) { // Itera de 1 a 4
println(s"Iteração (until): $i")
}
Guarda de Laço (Loop Guard)
Permite filtrar as iterações com base em uma condição. Funciona de forma semelhante ao continue em outras linguagens.
// Executa o bloco apenas se 'i' não for igual a 3
for (i <- 1 to 5 if i != 3) {
println(s"Iteração com guarda: $i")
}
// Equivalente a:
for (i <- 1 to 5) {
if (i != 3) {
println(s"Iteração com guarda: $i")
}
}
Passo do Laço (Loop Step)
Define o incremento entre as iterações.
// Itera de 2 em 2, de 0 a 10
for (i <- 0 to 10 by 2) {
println(s"Iteração com passo: $i")
}
Laços Aninhados
Laços for podem ser aninhados.
// Laço for aninhado
for (i <- 1 to 3; j <- 1 to 2) {
println(s"i: $i, j: $j")
}
// Equivalente a:
for (i <- 1 to 3) {
for (j <- 1 to 2) {
println(s"i: $i, j: $j")
}
}
Introdução de Variáveis
É possível definir variáveis dentro da estrutura do laço for.
for (i <- 1 to 4; soma = i + 10) {
println(s"i: $i, soma: $soma")
}
// Múltiplas definições separadas por ';'
for (i <- 1 to 3; j = 5 - i; k = i * j) {
println(s"i=$i, j=$j, k=$k")
}
Retorno de Laço com yield
A palavra-chave yield permite coletar os resultados de cada iteração em uma coleção (geralmente um Vector).
package controlefluxo
object ExemploFor {
def main(args: Array[String]): Unit = {
// Usando yield para criar um Vector com os quadrados dos números
val quadrados = for (i <- 1 to 10) yield i * i
println(s"Quadrados: $quadrados") // Saída: Quadrados: Vector(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
// Exemplo de laço aninhado com yield
val pares = for (i <- 1 to 3; j <- 1 to 2) yield (i, j)
println(s"Pares ordenados: $pares") // Saída: Pares ordenados: Vector((1,1), (1,2), (2,1), (2,2), (3,1), (3,2))
}
}
Laços de Repetição while e do-while
Funcionam de maneira semelhante às suas contrapartes em Java.
while
Executa um bloco de código repetidamente enquanto uma condição for verdadeira. A condição é verificada *entes* de cada iteração.
Laços while em Scala não retornam valores diretamente (o tipo de retorno é Unit), e seu uso é desencorajado em favor de abordagens mais funcionais, pois frequentemente requerem a mutação de variáveis externas.
do-while
Executa um bloco de código pelo menos uma vez e, em seguida, continua executando enquanto a condição for verdadeira. A condição é verificada *após* cada iteração.
package controlefluxo
object ExemploWhile {
def main(args: Array[String]): Unit = {
// Laço while
var contadorW: Int = 5
while (contadorW > 0) {
println(s"While: $contadorW")
contadorW -= 1
}
// Laço do-while
var contadorDoW: Int = 0
do {
println(s"Do-While: $contadorDoW")
contadorDoW += 1
} while (contadorDoW < 3)
}
}
Interrupção de Laços
Scala não possui as palavras-chave break e continue diretamente para se alinhar com a programação funcional. Em vez disso, utiliza-se a biblioteca scala.util.control.Breaks.
Usando Breaks.breakable
O método breakable envolve um bloco de código onde Breaks.break() pode ser chamado para sair do laço.
package controlefluxo
import scala.util.control.Breaks
import scala.util.control.Breaks.{breakable, break}
object ExemploInterrupcao {
def main(args: Array[String]): Unit = {
println("--- Usando breakable ---")
breakable {
for (i <- 1 to 10) {
if (i == 5) {
println("Interrompendo o laço em i = 5")
break() // Sai do bloco breakable
}
println(s"Processando: $i")
}
}
println("Laço 'breakable' concluído.")
// Exemplo de como simular 'continue' com if
println("\n--- Simulando 'continue' com if ---")
for (i <- 1 to 7) {
if (i % 2 == 0) { // Pula iterações pares
println(s"Pulando iteração par: $i")
// Em vez de 'continue', simplesmente não faz nada neste bloco
} else {
println(s"Processando iteração ímpar: $i")
}
}
}
}