IT Mídia
Notícias em destaque

Blocos em Ruby

31 de maio de 2011 19:53

Uma das características mais interessantes da linguagem de programação Ruby são os blocos, porções de códigos ou grupo de comandos que podem ser passados para outras funções e ser invocados por elas.

À primeira vista, para quem não conhece programação funcional e/ou é novato em Ruby, os blocos podem parecer um tanto complicados. Isso é normal no começo, mas conforme você vai se familiarizando e entendo melhor como as coisas acontecem, seu uso se torna fácil e natural.

O que já lhe adianto é que não tem como programar bem em Ruby sem usar blocos, então vale a pena aprender direito.

Quando estava começando a escrever esse post, lembrei de um ótimo artigo que o Satish Talim do Ruby Learning escreveu a respeito de blocos, o qual é muito didático e com exemplos simples e claros. Então eu trago a tradução desse artigo. Se quiser ver o original em inglês, acesse http://rubylearning.com/satishtalim/ruby_blocks.html.

Blocos em Ruby

Blocos (também chamados closures em outras linguagens) são definitivamente uma das características mais legais em Ruby e são pedaços de códigos entre chaves ou entre do end que podem ser associadas com invocações de métodos, quase como se fossem parâmetros. Um bloco é uma maneira de agrupar comandos e pode aparecer somente no código adjacente à chamada do método. O código no bloco não é executado no momento que é declarado. Ao invés disso, o Ruby se lembra do contexto em que o bloco aparece (as variáveis locais, o objeto atual, etc.) e então entra no método.

Nas convenções de escrita de código Ruby são usadas chaves para blocos de uma linha e do end para blocos com várias linhas. Lembre-se que a sintaxe de chaves são precedentes à sintaxe do end. Chaves têm precedência maior e do tem precedência menor. Se a invocação do método tem parâmetros que não são envolvidos em parênteses, a forma com chaves de um bloco irá utilizar o último parâmetro, não a invocação do bloco. A forma com do irá utilizar a invocação do bloco.

Matz diz que qualquer método pode ser chamado com um bloco como um argumento implícito. Dentro do método, você pode chamar o bloco usando a palavra-chave yield com um valor.

Também, como você verá em breve, blocos podem ter seus próprios argumentos. Há muitos métodos em Ruby que iteram em um range de valores. Muitos desse iteradores são escritos de uma maneira onde é possível fornecer um bloco de código como parte de sua sintaxe de chamada. O método pode então chamar o bloco com yield durante a execução quantas vezes for necessário para a interação completar (por exemplo, se nós estamos iterando nos valores de um array, nós podemos executar o bloco várias vezes enquanto houver itens no array).

Uma vez criado um bloco, você pode associá-lo com uma chamada de método. Normalmente os blocos passados para métodos são objetos anônimos, criados imediatamente. Por exemplo, no seguinte código, o bloco contendo puts “Hello” é associado com a chamada do método greet.

Se o método tem parâmetros, eles aparecem após o bloco:

Um método pode então invocar um bloco associado um ou mais vezes usando o comando yield. Dessa forma, qualquer método que quer receber um bloco como um parâmetro, pode usar a palavra-chave yield para executar o bloco a qualquer momento.

O código abaixo ilustra o que acabamos de discutir:

A saída será:

Se você fornecer um bloco na chamada de um método, então dentro do método você pode chamar o bloco com yield, suspendendo a execução do método, executar o código no bloco e retornar o controle para o corpo do método, logo após onde foi chamado o yield. Se nenhum bloco é passado, uma exceção é lançada:

Você pode fornecer parâmetros para chamada yield: eles serão passados para bloco. Dentro do bloco, você lista o nome dos argumentos para receber os parâmetros entre barras verticals (|):

A saída é:

Note que o código no bloco não é executado na hora que é encontrado pelo interpretador do Ruby. Ao invés disso, o Ruby se lembra do contexto no qual o bloco aparece e então entra no método.

O valor de retorno de um bloco (da mesma forma que um método) é o valor da última expressão executada no bloco. Esse valor de retorno também está disponível dentro do método, pois ele vem através do valor de retorno de yield.

block_given? retorna true se o comando yield está apto a executar um bloco no contexto atual. Veja o seguinte exemplo:

Variávies do Bloco

Vamos ver o que acontece no exemplo a seguir quando existe uma variável fora do bloco chamada x e um parâmetro do bloco também como o nome x.

A saída é:

Você irá observar que após o bloco ser executado, a variável x fora do bloco é a variável x original. Então o parâmetro x do bloco era de escopo local ao bloco.

Agora observe o que acontece com a variável x no próximo exemplo:

A saída é:

Desde que a variável x não é um parâmetro do bloco aqui, a variável x é a mesma dentro e fora do bloco.

No Ruby 1.9.1, os blocos introduziram seus próprios escopos apenas para os parâmetros de bloco. Isso é ilustrado no seguinte exemplo:

A saída é:

No bloco acima, a nova funcionalidade é usada: variável local de bloco. Resumindo, variáveis locais de bloco blindam um bloco da manipulação de suas variáveis fora do seu escopo. Isso previne qualquer sobrescrita não intencional das variáveis fora do seu escopo. Se você não quer problemas de sobrescritas não intencionais, use variáveis locais de bloco para as variáveis que seu bloco cria.

A sintaxe para variável local de bloco é simples. Coloque um ponto-e-vírgula após a lista de parâmetros normais do bloco, então liste a variável que você quer como variável local do bloco. Por exemplo, se o bloco recebe duas variáveis a e b, e usa as variáveis locais x e y, a lista de parâmetros deveria ser algo como: |a, b; x, y|.

TAGS: ruby

Sobre Fernando Hamasaki de Amorim

Desenvolvedor sênior na Locaweb, empresa na qual está desde 2007, Fernando Hamasaki de Amorim trabalha desde a criação até a arquitetura, modelagem, análise e integração de sistemas e aplicativos na companhia. Graduado em Tecnologia em Informática pela UniSant'Anna, o profissional possui pós-graduação em Tecnologias Web com Ênfase em Java pela Fiap. Já atuou em diversas outras companhias, tais como a TV Online, empresa brasileira pioneira em transmissões ao vivo e SAC Sistemas, que desenvolve ERP. Neste espaço, abordará temas envolvendo o desenvolvimento por meio da linguagem Ruby.

Entre em contato com Fernando Hamasaki de Amorim

Parceiros

Portais: IT Mídia | IT Web | Saúde Web

Publicações: InformationWeek Brasil | CRN Brasil | FH

Fóruns: IT Forum | IT Forum + | IT Business Forum | Saúde Business Forum