Para trabalhar com coleção de dados, filtrar informações, decidir quais instruções ou blocos de código serão executados, ordenar valores, converter um valor de um tipo para outro, entre outras operações, o Ruby fornece vários recursos que permitem executar essas operações. Analisaremos como funciona cada um em detalhes.
Para acompanhar os exemplos que serão mostrados nesse artigo é necessário ter instalado o Ruby em sua máquina., que dependerá do sistema operacional que está sendo usado. A fim de saber se a instalação foi efetuada com sucesso, abra o seu terminal ou prompt de comando e digite ruby --version ou o seu atalho equivalente ruby -v. A resposta deve ser algo parecido com o seguinte:
ruby 2.0 (2014-05-08) [x86_64-linux-gnu]
No pacote de instalação vem o IRB, que utilizaremos para executar alguns exemplos que serão mostrados neste artigo. Ele é uma ferramenta que faz a leitura de instruções ou códigos ruby e as interpreta instantaneamente, mostrando o resultado, além de ser muito usado para execução de testes rápidos. Para iniciar essa ferramenta basta digitar o comando “irb” no terminal.
Junto da instalação também encontramos o interpretador ruby, que serve para abrirmos os exemplos em que os códigos estarão em arquivos com a extensão “.rb”. Nestes casos será necessário invocá-lo no terminal ou console. Por exemplo, para que o código de um arquivo chamado teste.rb,, armazenado no diretório /home/daniel/exemplos-ruby/, seja executado basta digitar o comando a seguir no prompt ou terminal:
ruby /home/daniel/exemplos-ruby/teste.rb
Ou caso já tenha chegado pelo console até o diretório onde se encontra o arquivo (no exemplo apresentado - /home/daniel/exemplos-ruby/), bastaria digitar ruby teste.rb
A seguir passaremos para a parte prática do nosso artigo. Inicialmente conheceremos melhor métodos que podem nos ajudar na execução dos exemplos.
Praticando com Gets
Para começarmos a praticar, primeiro devemos estar com o IRB aberto.
Uma dica é o uso do método gets durante todo o artigo para deixar os exemplos mais dinâmicos e interessantes, pois ele pode ser usado no console para solicitar uma entrada de dados ao usuário. Assim, o que ele digitar será tratado como uma String, como vemos no exemplo da Listagem 1.Listagem 1. Exemplo com IRB
irb(main):001:0> nome = gets
joão da silva souza
irb(main):002:0> puts nome
joão da silva souza
=> nil
Perceba que após digitar a instrução gets no terminal o irb ficará aguardando que seja digitado algo. Para o código da Listagem 1 o que for digitado será armazenado na variável nome e comprovamos isso ao imprimir a variável usando o método puts.
A partir da próxima seção entenderemos mais algumas estruturas de dados para colocar os nossos exemplos em prática.
Estruturas de Controle de fluxo
Algumas aplicações necessitam decidir o que vai ser executado baseado em alguma condição. Para isso a linguagem Ruby disponibiliza recursos que são chamados estruturas de decisão, que tem o objetivo de controlar justamente o fluxo de execução da aplicação.
Precisamos antes conhecer alguns operadores que farão parte das condições a serem analisadas nos códigos. Para isso acompanhe as próximas seções.
Operadores aritméticos
Os operadores aritméticos na linguagem ruby são métodos dos objetos que representam números. Pode-se comprovar isso ao chamar o método methods, que retorna todos os métodos disponíveis para um objeto. Se essa chamada for feita, por exemplo, em uma instância de um objeto Fixnum, a resposta conterá o seguinte:
:+, :-, :*, :/
Isso indica que esse objeto reponde aos métodos + (adição) – (subtração) * (multiplicação) e / (divisão), que podem, inclusive, serem sobrescritos mudando o seu comportamento. A chamada a esses métodos é feita de forma transparente, o que faz com que o desenvolvedor imagine o método como um operador.
Operadores relacionais
Os operadores relacionais são facilmente entendidos visto que são bastante utilizados na matemática, conforme vemos na Tabela 1.
Símbolo | Descrição | Exemplo | Resultado |
> | Maior que | 6 > 8 | Falso |
< | Menor que | 7< 10 | Verdadeiro |
>= | Maior ou igual a | 8 >= 8 | Verdadeiro |
<= | Menor ou igual a | 7 <= 2 | Falso |
!= | Diferente de | != 8 | Verdadeiro |
== | Igual a | 10 = 10 | Verdadeiro |
Tabela 1. Operadores Relacionais
Não se deve fazer confusão entre os operadores “==” e “=”, pois o primeiro serve para comparar a igualdade enquanto o segundo serve como atribuição.
Operadores lógicos
Os operadores lógicos têm o objetivo de fazer uma junção entre condições resultando em um novo valor booleano, conforme vemos na Tabela 2.
Operador | Descrição | Exemplo | Resultado |
and / && | E | 6 > 8 and 7 > 8 | Falso |
or / || | Ou | 10< 10 or 15 > 1 | Verdadeiro |
not / ! | Não | ! true | Falso |
Tabela 2. Operadores lógicos
A diferença entre os operadores “e” e “ou” é que o primeiro retorna verdadeiro apenas se as duas expressões retornarem verdadeiras e a segunda retorna verdadeiro mesmo que uma das expressões seja avaliada como falsa. Já o operador not inverte o valor lógico de true para false e vice-versa. Na Listagem 2 temos alguns exemplos executados no IRB.
Listagem 2. Exemplos com operadores
irb(main):001:0> 10 < 8 and 7 > 5
=> false
irb(main):002:0> 8 == 9 or 6 > 3
=> true
irb(main):003:0> 10 > 9 && 1 > 0
=> true
irb(main):004:0> 7 == 7 || 6 > 8
=> true
irb(main):005:0> not(10 == 10)
=> false
irb(main):006:0> !false
=> true
A partir das próximas seções conheceremos algumas estruturas de decisão e que usarão os operadores apresentados.
Estruturas de decisão
If
Instruções if's são usadas para decidir se determinada instrução será executada. Imagine que o usuário deva digitar a sua idade e esse é avaliado. Na Listagem 3 o código usa uma instrução if para fazer essa validação.
Listagem 3. Exemplo com if
puts "Informe a sua idade"
idade = gets.to_i
if idade < 0
puts "essa não é uma idade válida"
end
A primeira instrução no código solicita ao usuário que digite a idade do mesmo e em seguida o valor retornado pelo método gets é convertido em um inteiro através da chamada ao método to_i e é armazenado na variável idade. Na linha 3 é vista a instrução if que “pergunta” se a idade digitada é menor que zero, ou seja, se ela é negativa: caso isso seja verdade a mensagem “essa não é uma idade válida” será impressa no console.
Else
Essa instrução é executada caso a condição if não seja verdadeira. É possível incrementar o exemplo da Listagem 3 com a instrução else, como mostra a Listagem 4.
Listagem 4. Exemplo com else
puts "Informe a sua idade"
idade = gets.to_i
if idade < 0
puts "essa não é uma idade válida"
else
puts "essa é uma idade válida"
end
Quando o usuário digitar uma idade maior que zero ele receberá a mensagem “essa é uma idade válida”.
Elsif
Caso seja necessário validar mais de uma condição, a instrução elsif pode ser usada. Por exemplo, imagine um caso em que se deve verificar se a idade de um usuário é compatível com o conteúdo que ele deseja acessar. Veja como fica o exemplo na Listagem 5.
Listagem 5. Exemplo com elsif
puts "Informe a sua idade"
idade = gets.to_i
if idade >= 0 and idade < 18
puts "ops! você não tem acesso a esse conteúdo"
elsif idade >= 18
puts "Olá! seja bem vindo, visitante!"
else
puts "Essa não é uma idade válida"
end
A instrução if verifica se a idade digitada pelo usuário é maior ou igual a 0 (>=) e (and) < 18. Caso essa condição não satisfaça, o interpretador verificará a condição passada para a instrução elsif, que afere se a variável idade é maior ou igual a 18 (>=). Caso essa instrução retorne true (verdadeiro), a mensagem “Olá! seja bem vindo, visitante!” será impressa. Em seguida, a instrução else será executada se nenhuma das duas instruções anteriores forem verdadeiras - por exemplo, no caso do usuário digitar um valor negativo.
Unless
A instrução unless (a menos que) tem o funcionamento oposto ao if, ou seja, o bloco de código associado só será executado caso a condição seja falsa. Veja o código da Listagem 6 em que o resultado impresso é “x é menor ou igual a 15”.
Listagem 6. Exemplo com Unless
x = 10
unless x > 15 # → a menos que x seja maior que 15
puts "x é menor ou igual a 15"
else
puts "x é maior que 15"
end
Case
No caso de ser necessário avaliar uma expressão e houverem muitas condições, a instrução case é preferível ao invés da instruçãoif, como na Listagem 7.
Listagem 7. Exemplo com case
puts "Informe sua idade"
idade = gets.to_i
case idade
when 0..12
puts "você é uma criança"
when 13..17
puts "você é um adolescente"
else
puts "você é um adulto"
end
When
A instrução when (quando) testa se o valor informado está entre os ranges (intervalos) delimitados por dois números inteiros. É possível fazer o mesmo usando if's, mas é notável a perda de legibilidade, como mostra o exemplo da Listagem 8.
Listagem 8. Exemplo com When
puts "Informe sua idade"
idade = gets.to_i
if idade < 12
puts "você é uma criança"
elsif idade >= 13 and idade <= 17
puts "você é um adolescente"
else
puts "você é um adulto"
end
Exemplo prático – Estruturas de decisão
Para completar o aprendizado visto até agora, vamos criar uma calculadora que utiliza as instruções da linguagem, como mostra a Listagem 9.
Listagem 9. Calculadora
puts "informe o primeiro operando"
operando1 = gets.to_i
puts "informe o segundo operando"
operando2 = gets.to_i
puts "informe 1 para soma 2 para subtração 3 para multiplicação e 4 para divisão"
operacao = gets.to_i
case operacao
when 1
puts "O resultado é #{operando1 + operando2}"
when 2
puts "O resultado é #{operando1 - operando2}"
when 3
puts "O resultado é é #{operando1 * operando2}"
when 4
puts "O resultado é #{operando1 / operando2}"
else
puts "Operação inválida"
end
Neste exemplo usamos o método gets para capturar os valores que o usuário digitar para os dois operandos e também para a operação desejada. Em seguida foi usada a instrução case para determinar qual das quatro operações deve ser realizada com os operandos informados.
Concluído o aprendizado sobre as estruturas condicionais, aprenderemos a seguir sobre as estruturas de repetição, que podem ser usadas com as que aprendemos até agora.
Estruturas de repetição
As estruturas de repetição são também muito usadas para executar uma determinada operação várias vezes como, por exemplo, percorrer ou iterar uma lista de produtos para mostrar o nome de cada um ou para efetuar o cálculo do valor total deles. A seguir veremos as estruturas de repetição mais usadas na linguagem ruby.
While
Podemos usar o a instrução while para executar determinada tarefa um número específico de vezes. A sintaxe para o uso dessa expressão é a seguinte:
while [codicao] do
# operação a ser repetida aqui
end
Veja na Listagem 10um exemplo para essa instrução com uma contagem simples de 0 a 10 usando o IRB.
Listagem 10. Exemplo com While
irb(main):001:0> contador = 0
=> 0
irb(main):002:0> while contador <= 10 do
irb(main):003:1* print "#{contador}, "
irb(main):004:1> contador += 1
irb(main):005:1> end
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, => nil
Note que para este caso foi usada uma variável (contador) que armazenou, a cada iteração, o valor corrente, que a cada iteração teve o seu valor incrementado com mais 1: isso é importante para que a condição seja em algum momento satisfeita, evitando um loop infinito.
Until
Boa parte das linguagens famosas hoje em dia não colocam a disposição do desenvolvedor uma estrutura semelhante a essa. O bloco de código associado a ela só é executado a menos que determinada condição seja satisfeita, ou seja, para que o código seja executado é necessário que a condição retorne false.Quando ela retornar true o bloco para de ser executado, como vemos na sintaxe a seguir:
until [condicao] do
# operação a ser repetida aqui
end
O exemplo da Listagem 11, executado no IRB, mostra o seu funcionamento.
Listagem 11. Exemplo com until
irb(main):001:0> contador = 10
irb(main):002:0> until contador == 0 do
irb(main):003:1* print "#{contador}, "
irb(main):004:1> contador -= 1
irb(main):005:1> end
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, => nil
O exemplo confirma que quando a condição retorna verdadeiro (neste caso quando o contador se tornou igual a zero) o bloco de código para de ser executado.
For
A estrutura for é bem semelhante ao while, com a diferença de que tem a declaração da variável, que auxilia as iterações em sua própria estrutura, como mostra a sintaxe a seguir:
for [elemento] in [elementos_a_serem_percorridos] do
end
Em ruby essa estrutura é mais frequentemente usada para percorrer lista de objetos que tenham implementado o método each, que é um método que aceita um bloco de código e que depois o executa para cada elemento numa lista. Uma tentativa de usá-lo em um tipo numérico como Fixnum resultaria em um erro, como vemos na Listagem 12.
Listagem 12. Exemplo com for
irb(main):001:0> for contador in 10 do
irb(main):002:1* print #{contador}, "
irb(main):003:1> end
NoMethodError: undefined method `each' for 10:Fixnum
from (irb):1
from /usr/bin/irb:11:in `<main>'
O método each está disponível por exemplo paraarray's e range's. O problema relatado pode ser corrigido usando um range (intervalo), como mostra a Listagem 13.
Listagem 13. Exemplo com each
irb(main):001:0> for e in 0..10 do
irb(main):002:1* print "#{e}, "
irb(main):003:1> end
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, => 0..10
Repare que não foi necessário incrementar a variável “e”, pois a própria estrutura de repetição se encarrega de armazenar o próximo elemento nesta variável.
Com o for também é possível percorrer elementos em um array, como mostra a Listagem 14.
Listagem 14. Exemplo com array
irb(main):001:0> linguagens = ["ruby", "java", "python", "php", "lua"]
irb(main):002:0> for linguagem in linguagens do
irb(main):003:1* print "#{linguagem}, "
irb(main):004:1> end
ruby, java, python, php, lua
Existe também a possibilidade de percorrer estruturas mais complexas como os hash's. A interação com um desses é levemente diferente do array, já que cada elemento inserido em um hash é um conjunto de chaves associado a um valor. Em cada iteração do for o conjunto chave e valor é colocado em um arraypara acessá-los por meio dos seus índices, como mostra a Listagem 15.
Listagem 15. Exemplo com hash
irb(main):001:0> produtos = {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
irb(main):002:0> for produto in produtos do
irb(main):003:1* puts "#{produto[0]} - #{produto[1]}"
irb(main):004:1> end
mouse - 30.0
monitor - 500.0
fone - 90.0
O exemplo parece muito verboso e não elegante, por isso o ruby disponibiliza ainda outra maneira de percorrer os elementos de um hash com o método each, assim não é necessário acessar o conjunto chave e valor por meio de índices, como mostra a Listagem 16.
Listagem 16. Exemplo de hash com each
irb(main):001:0> produtos = {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
irb(main):002:0> produtos.each do |produto, preco|
irb(main):003:1* puts "#{produto} - #{preco}"
irb(main):004:1> end
mouse - 30.0
monitor - 500.0
fone – 90.0
E ainda, se for necessário iterar apenas sobre as chaves ou sobre os valores, temos os métodos each_key e each_value, como mostra os exemplos da Listagem 17.
Listagem 17. Exemplos com each_key e each_value
irb(main):001:0> produtos = {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
=> {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
irb(main):002:0> produtos.each_key do |produto|
irb(main):003:1* print "#{produto}, "
irb(main):004:1> end
mouse, monitor, fone
irb(main):001:0> produtos = {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
=> {:mouse=>30.0, :monitor=>500.0, :fone=>90.0}
irb(main):002:0> produtos.each_value do |produto|
irb(main):003:1* print "#{produto}, "
irb(main):004:1> end
30.0, 500.0, 90.0
Times
A linguagem ruby ainda disponibiliza o iterador chamado times (vezes). Se é necessário executar uma tarefa um número determinado de vezes isso pode ser feito da seguinte maneira:
irb(main):001:0> 5.times{print "Devmedia "}
Devmedia Devmedia Devmedia Devmedia Devmedia => 5
Se o código a ser executado precisa estar disposto em mais de uma linha, as chaves devem ser substituídas pelas palavras reservadas do e end, como mostrado na Listagem 18.
Listagem 18. Exemplo com times
irb(main):001:0> 5.times do
irb(main):002:1* print "Devmedia "
irb(main):003:1> end
Devmedia Devmedia Devmedia Devmedia Devmedia => 5
Também é possível usar o iterador times com uma variável contadora ou de iteração. O código da Listagem 19mostra como.
Listagem 19. Exemplo com variável
irb(main):001:0> 10.times do |contador|
irb(main):002:1* print "#{contador} "
irb(main):003:1> end
0 1 2 3 4 5 6 7 8 9 => 10
Exemplo prático – Estruturas de repetição
Este tópico mostra a criação de um exemplo simples utilizando recursos que já foram apresentados. Mas para este exemplo é necessário um pequeno conhecimento a respeito do método rand, que escolhe aleatoriamente um número baseado em um limite ou intervalo. Veja na Listagem 20um pequena demonstração de como ele funciona.
Listagem 20. Exemplo com rand
irb(main):001:0> rand(3)
=> 0
irb(main):002:0> rand(3)
=> 2
irb(main):003:0> rand(3)
=> 1
irb(main):004:0> rand(0..3)
=> 1
irb(main):005:0> rand(0..3)
=> 2
irb(main):006:0> rand(0..3)
=> 3
Neste exemplo esse método será usado para escolher um número aleatório, que deverá ser adivinhado pelo usuário. Também será usada a estrutura de controle while, bem como o método gets, como mostra a Listagem 21.
Listagem 21. Exemplo de controle While
numero = rand(0..15)
puts "Tente adivinhar o número escolhido pela máquina de 0 a 15"
numero_chute = gets.to_i
while numero != numero_chute do
puts "Ooops! Tente novamente!"
numero_chute = gets.to_i
end
puts "Parabens você acertou! O número é: #{numero}"
A aplicação inicia usando o método rand para escolher um número aleatório entre 0 e 15. Depois disso solicita ao usuário que informe um número qualquer que será o seu palpite. O laço while é usado para continuar solicitando ao usuário outros palpites até que ele consegue a acertar o número inicialmente escolhido e assim o programa encerra.
Ao longo desse artigo você pode perceber que programar com ruby não envolve muita dificuldade, pois ela é uma linguagem bem simplificada a nível de quantidade de código. As estruturas aprendidas aqui são essenciais para o desenvolvimento de qualquer aplicativo, por menor que seja.
Referências
Ruby lang
https://www.ruby-lang.org/pt
Ruby doc
http://ruby-doc.org/core-1.9.3/Random.html
DotNet Perls
http://www.dotnetperls.com/iterator
Techotopia
http://www.techotopia.com/index.php/Ruby_While_and_Until_Loops