Iteradores e blocos

Iteradores são métodos que executam um bloco de código que lhes seja passado. Blocos são delimitados por { ... }, ou do ... end ({} tem maior precedência), e podem receber argumentos, declarados entre | ... |.

"abcdef".each_byte { |c|  # O método each_byte vai executar o bloco para cada byte da string,
  print c, " "            # lhe passando cada byte pelo argumento c
}

Quando definindo iteradores, o bloco recebido é executado pelo comando yield, e os argumentos passados a yield serão atribuídos aos argumentos do bloco por atribuição múltipla.

class ListaEncadeada
  ...
  def each
    ...                # Passa por todos os elementos
      yield(elemento)  # executando o bloco recebido, com o elemento atual como argumento
  end
end

lista = ListaEncadeada.new
...
lista.each { |e| print e }

Iteradores são muito úteis em substituição a laços, em muitos casos. Note que blocos não são úteis apenas à iteradores. Eles podem ser passados a qualquer método. Além disso, blocos podem ser convertidos em objetos Proc, e dessa forma atribuídos a variáveis, passados como argumentos normais, etc..

def teste(um_bloco)
  um_bloco.call
end

bloco = proc {
  puts "oi!"
}

teste(bloco)    # >> oi!

É importante destacar algo que pode ser fonte de confusão. O contexto de variáveis do bloco é o mesmo de onde ele foi criado. O bloco tem acesso às variáveis locais do bloco onde foi criado, por exemplo. Mas o bloco não introduz novas variáveis no contexto onde foi criado, apenas no seu próprio. Ou seja, variáveis já existentes podem ser usadas em um bloco (inclusive variáveis de instância, de classe, e globais), e variáveis de um bloco são locais ao bloco, caso não existem anteriormente.

l = "z"
m = "1"
["a", "b", "c"].each { |l|
  print l  # >> abc
  m = "2"
  n = l
}
puts l     # >> c
puts m     # >> 2
puts n     # >> NameError: undefined local variable or method `n' ...

topo da página

<< Página Anterior | índice | Próxima Página >>
Apostilas de Ruby e RGSS

nossos tutoriais

navegue

livros recomendados