Dominando os Tipos Básicos em Ruby: Números, Strings e Ranges
Embora já tenhamos nos divertido implementando programas usando arrays, hashes e procs, ainda não cobrimos os tipos mais fundamentais do Ruby: números, strings e ranges. Vamos dedicar este tutorial a esses blocos de construção essenciais que todo desenvolvedor Ruby precisa dominar.
Números em Ruby: Mais Poderosos do que Você Imagina
Ruby oferece suporte robusto para diversos tipos numéricos: inteiros, ponto flutuante, racionais e complexos. Uma das características mais impressionantes é que os inteiros podem ter qualquer comprimento, limitados apenas pela memória disponível do sistema.
Representando Números em Diferentes Bases
# Diferentes formas de representar o mesmo número
numero_decimal = 123456 # base 10
numero_decimal_explicito = 0d123456 # base 10 explícita
numero_legivel = 123_456 # underscore ignorado para legibilidade
# Outras bases numéricas
numero_hexadecimal = 0xaabb # hexadecimal (43707)
numero_octal = 0377 # octal (255)
numero_binario = -0b10_1010 # binário negativo (-42)
# Para números muito grandes
numero_gigante = 123_456_789_123_456_789
puts numero_gigante # => 123456789123456789
Números Racionais: Precisão Matemática
Uma das funcionalidades mais elegantes do Ruby são os números racionais, que representam frações exatas:
# Cuidado: divisão normal retorna inteiro
puts 3/4 # => 0
# Diferentes formas de criar racionais
puts 3/4r # => (3/4)
puts 0.75r # => (3/4)
puts "3/4".to_r # => (3/4)
puts Rational(3, 4) # => (3/4)
puts Rational("3/4") # => (3/4)
Números Complexos: Matemática Avançada
Ruby também suporta números complexos com sintaxe literal simples:
# Diferentes formas de criar números complexos
numero_complexo = 1+2i # => (1+2i)
numero_complexo2 = "1+2i".to_c # => (1+2i)
numero_complexo3 = Complex(1, 2) # => (1+2i)
# Números podem ser racionais E complexos
numero_especial = 5.7ri # r antes do i!
Como os Números Interagem
Uma regra importante: operações entre diferentes tipos numéricos retornam o tipo mais geral:
# Regras de conversão automática
puts 1 + 2 # => 3 (inteiro)
puts 1 + 2.0 # => 3.0 (float)
puts 1.0 + 2 # => 3.0 (float)
puts 1.0 + 1+2i # => (2.0+2i) (complexo)
puts 1 + 2/3r # => (5/3) (racional)
# Diferentes formas de obter divisão com decimais
puts 1 / 2 # => 0 (divisão inteira)
puts 1.0 / 2 # => 0.5
puts 1.to_f / 2 # => 0.5
puts 1.fdiv(2) # => 0.5
Iterando com Números
Os números em Ruby oferecem métodos poderosos para iteração, substituindo loops tradicionais:
# Diferentes formas de iterar
3.times { print "X " } # X X X
1.upto(5) { |i| print i, " " } # 1 2 3 4 5
99.downto(95) { |i| print i, " " } # 99 98 97 96 95
50.step(80, 5) { |i| print i, " " } # 50 55 60 65 70 75 80
Strings: Muito Mais que Texto Simples
As strings em Ruby são sequências de caracteres extremamente versáteis. Elas podem conter texto imprimível ou dados binários, e oferecem múltiplas formas de criação e manipulação.
Literais de String e Escape Sequences
# String com aspas simples - literais
texto_simples = 'escape usando "\\"' # => escape usando "\"
texto_aspas = 'That\'s right' # => That's right
# String com aspas duplas - escape sequences e interpolação
texto_com_quebra = "Primeira linha\nSegunda linha"
texto_interpolado = "Segundos/dia: #{24 * 60 * 60}" # => Segundos/dia: 86400
saudacao = "#{'Oi! ' * 3}Feliz Natal!" # => Oi! Oi! Oi! Feliz Natal!
Delimitadores Flexíveis
Ruby oferece sintaxes alternativas para quando você precisa usar as próprias aspas dentro da string:
# %q = aspas simples, %Q = aspas duplas
string_simples = %q/string com aspas simples/
string_dupla = %Q!string com aspas duplas!
string_interpolada = %Q{Segundos/dia: #{24*60*60}}
# % sozinho = aspas duplas
string_default = %!string com aspas duplas!
string_parenteses = %(Segundos/dia: #{24*60*60})
Here Documents (Heredoc)
Para strings multi-linha, Ruby oferece a sintaxe heredoc:
def string_longa
<<~FIM_DA_STRING
Mais rápido que uma bala, mais poderoso que
uma locomotiva, capaz de pular prédios altos
num único salto—olhe, lá no céu, é um pássaro,
é um avião, é o Superman!
FIM_DA_STRING
end
puts string_longa
Exemplo Prático: Processando Dados de Playlist
Vamos ver um exemplo prático de manipulação de strings processando um arquivo de playlist musical:
# Estrutura para armazenar dados da música
Musica = Struct.new(:titulo, :artista, :duracao)
# Exemplo de linha do arquivo:
# /jazz/j00132.mp3 | 3:45 | Fats Waller | Ain't Misbehavin'
linha_exemplo = "/jazz/j00132.mp3 | 3:45 | Fats Waller | Ain't Misbehavin'"
# Separar campos usando regex
_arquivo, duracao, artista, titulo = linha_exemplo.split(/\s*\|\s*/)
# Remover espaços extras do nome do artista
artista_limpo = artista.squeeze(" ") # "Fats Waller" -> "Fats Waller"
# Converter duração de mm:ss para segundos
minutos, segundos = duracao.scan(/\d+/) # ["3", "45"]
duracao_segundos = minutos.to_i * 60 + segundos.to_i
# Criar objeto da música
musica = Musica.new(titulo, artista_limpo, duracao_segundos)
puts musica
# => #
Ranges: Sequências e Intervalos Elegantes
Os ranges em Ruby representam sequências de valores com início, fim e forma de gerar valores sucessivos. Eles são fundamentais para expressar intervalos de forma natural e eficiente.
Ranges como Sequências
# Range inclusivo (dois pontos)
numeros_inclusivo = 1..10 # inclui 1 e 10
letras = "a".."z" # todas as letras
# Range exclusivo (três pontos)
numeros_exclusivo = 0...3 # inclui 0, 1, 2 (exclui 3)
# Converter para array
puts (1..10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
puts ('bar'..'bat').to_a # => ["bar", "bas", "bat"]
# Ranges infinitos
array_exemplo = [1, 2, 3, 4, 5, 6]
puts array_exemplo[..2] # => [1, 2, 3] (do início até índice 2)
puts array_exemplo[2..] # => [3, 4, 5, 6] (do índice 2 até o fim)
Métodos Úteis com Ranges
digitos = 0..9
# Testando inclusão
puts digitos.include?(5) # => true
# Valor máximo
puts digitos.max # => 9
# Rejeitar valores menores que 5
puts digitos.reject { |i| i < 5 } # => [5, 6, 7, 8, 9]
# Somar todos os valores
puts digitos.reduce(:+) # => 45
Ranges como Intervalos
Uma aplicação poderosa dos ranges é como testes de intervalo, especialmente em declarações case:
# Testando se um valor está em um intervalo
puts (1..10) === 5 # => true
puts (1..10) === 15 # => false
puts (1..10) === 3.14159 # => true
# Aplicação prática: classificando idade de carros
idade_carro = 9.5
case idade_carro
when 0...1
puts "Mmm.. cheiro de carro novo"
when 1...3
puts "Novo e bonito"
when 3...10
puts "Confiável mas com alguns arranhões"
when 10...30
puts "Carro velho"
else
puts "Relíquia vintage"
end
# => Confiável mas com alguns arranhões
Diferença entre include? e cover?
É importante entender a diferença entre estes dois métodos ao trabalhar com ranges:
range_letras = 'a'..'j'
# include? verifica se o valor está na sequência
puts range_letras.include?('c') # => true
puts range_letras.include?('bb') # => false (não existe na sequência)
# cover? verifica se está entre início e fim
puts range_letras.cover?('bb') # => true (está entre 'a' e 'j')
Armadilha Comum: Strings Numéricas
Uma pegadinha importante para desenvolvedores vindos de outras linguagens: strings que contêm apenas dígitos não são automaticamente convertidas em números:
# PROBLEMA: Tentando somar números de um arquivo
dados_exemplo = ["3 4", "5 6", "7 8"]
dados_exemplo.each do |linha|
v1, v2 = linha.split # dividir linha em espaços
print v1 + v2, " " # ERRO: concatena strings!
end
# Saída: 34 56 78 (concatenação, não soma!)
# SOLUÇÃO: Converter explicitamente para inteiros
dados_exemplo.each do |linha|
v1, v2 = linha.split
print Integer(v1) + Integer(v2), " "
end
# Saída: 7 11 15 (soma correta!)
Conclusão
Dominar os tipos básicos do Ruby - números, strings e ranges - é fundamental para escrever código Ruby idiomático e eficiente. Estes tipos oferecem funcionalidades ricas que vão muito além do que encontramos em linguagens mais simples. Os números suportam diferentes bases e tipos matemáticos avançados, as strings oferecem múltiplas sintaxes e manipulação poderosa, e os ranges proporcionam uma forma elegante de expressar sequências e intervalos.
Lembre-se sempre de converter strings para números quando necessário, aproveite a flexibilidade dos diferentes delimitadores de string, e use ranges para tornar seu código mais expressivo e legível. Esses conceitos serão a base sólida para tudo que construirmos daqui em diante no Ruby.
Nenhum comentário:
Postar um comentário