Blocos e iteradores em Ruby
As duas sintaxes para criar um bloco de código:
{ puts "Alô, Mundo!" } # note as chaves
# ou: do puts "Alô, Mundo!" end
Um bloco de código pode ser passado a um método com um argumento opcional do bloco. Várias métodos internos possuem tais argumentos:
File.open('file.txt', 'w') do |file| # 'w' denota "modo de escrita" file.puts 'Wrote some text.' end # o arquivo é automaticamente fechado aqui File.readlines('file.txt').each do |line| puts line end # => Escreveu algum texto.
Passagem de um parâmetro de um bloco com fechamento:
(também fechamento lexical ou fechamento de função) é uma função ou referência a uma função, juntamente com um ambiente de referência. Um fechamento, ao contrário de uma função simples ponteiro permite que uma função possa acessar essas variáveis não-locais, mesmo quando chamado fora de seu escopo lexical imediato.
# In an object instance variable (denoted with '@'), remember a block. def remember(&a_block) @block = a_block end # Invoke the preceding method, giving it a block which takes a name. remember {|name| puts "Hello, #{name}!"} # Call the closure: @block.call("Jon") # => "Hello, Jon!"
Criado uma função anônima:
proc {|arg| puts arg} Proc.new {|arg| puts arg} lambda {|arg| puts arg} ->(arg) {puts arg} # introduced in Ruby 1.9
Retornando o fechamento de um método:
def create_set_and_get(initial_value=0) # note the default value of 0 closure_value = initial_value return Proc.new {|x| closure_value = x}, Proc.new { closure_value } end setter, getter = create_set_and_get # returns two values setter.call(21) getter.call # => 21 # Parameter variables can also be used as a binding for the closure, # so the preceding can be rewritten as: def create_set_and_get(closure_value=0) return proc {|x| closure_value = x } , proc { closure_value } end
Cedendo o fluxo de controle do programa para um bloco que foi fornecido no momento da chamada:
def use_hello yield "hello" end # Invoke the preceding method, passing it a block. use_hello {|string| puts string} # => 'hello'
Iterações sobre enumerações e arrays utilizando blocos:
array = [1, 'hi', 3.14] array.each {|item| puts item } # prints: # 1 # 'hi' # 3.14 array.each_index {|index| puts "#{index}: #{array[index]}" } # prints: # 0: 1 # 1: 'hi' # 2: 3.14 # The following uses a Range (3..6).each {|num| puts num } # prints: # 3 # 4 # 5 # 6
Um método como
inject
pode aceitar ambos, um parâmetro e um bloco. Ele faz iteração sobre cada membro da list, executa algumas funções nele enquanto mantem um agregado.[1,3,5].inject(10) {|sum, element| sum + element} # => 19
Na primeira passagem, o bloco recebe 10 (o argumento para inject) como soma, e um (o primeiro elemento da array) como element. Isso retorna 11, que torna-se então soma na próxima passagem. Ele é adicionado a 3 para obter 14, que é então adicionada a 5 no terceiro passo, para finalmente voltar 19.
Usando uma enumeração e um bloco ao quadrado os números de 1 a 10 (com um intervalo):
(1..10).collect {|x| x*x} # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Ou invoca um método a cada item (
map
é um sinônimo para collect
):(1..5).map(&:to_f) # => [1.0, 2.0, 3.0, 4.0, 5.0]
Função anônima (também função constante, função literal ou função lambda) é uma função (ou uma sub-rotina) definida, e possivelmente chamada, sem estar vinculado a um identificador.
Funções anônimas são convenientes para passar como um argumento para uma função de ordem superior e são onipresentes em línguas com funções de primeira classe.
É uma forma de função aninhada, na medida em que permitem o acesso a variáveis no escopo da função que contém (variáveis não- locais). Ao contrário das funções aninhadas nomeadas, elas não podem ser recursiva sem a assistência de um operador fixpoint ( também conhecido como um fixpoint anônimo ou recursão anônimo) .
Nenhum comentário:
Postar um comentário