collect
usa n:
# multiply each element of the data array by n
def multiply(data, n)
data.collect {|x| x*n }
end
puts multiply([1,2,3], 2) # Prints 2,4,6
n
permanece mas allá de multiplier. Es esta característica la
que hace que la lambda doubler sea una clausura:
# Return a lambda that retains or "closes over" the argument n
def multiplier(n)
lambda {|data| data.collect{|x| x*n } }
end
doubler = multiplier(2) # Get a lambda that knows how to double
puts doubler.call([1,2,3]) # Prints 2,4,6
doubler encapsula o clausura con la lambda el binding
de n
def accessor_pair(initialValue=nil)
value = initialValue # A local variable shared by the returned lambdas.
getter = lambda { value } # Return value of local variable.
setter = lambda {|x| value = x } # Change value of local variable.
return getter,setter # Return pair of lambdas to caller.
end
getX, setX = accessor_pair(0) # Create accessor lambdas for initial value 0.
puts getX[] # Prints 0. Note square brackets instead of call.
setX[10] # Change the value through one closure.
puts getX[] # Prints 10. The change is visible through the other.
$ cat closure_shared_variables.rb
# Return an array of lambdas that multiply by the arguments
def multipliers(*args)
# x = nil
args.map {|x| lambda {|y| x*y }}
end
double,triple = multipliers(2,3)
puts double.call(2)
$ rvm use 1.8.7 Using /Users/casiano/.rvm/gems/ruby-1.8.7-p352 $ ruby closure_shared_variables.rb 4Veamos que ocurre cuando descomentamos la línea
# x = nil:
$ cat closure_shared_variables.rb
# Return an array of lambdas that multiply by the arguments
def multipliers(*args)
x = nil
args.map {|x| lambda {|y| x*y }} # En 1.8 la |x| es la misma x
end # local
double,triple = multipliers(2,3)
puts double.call(2) # Prints 6 in Ruby 1.8
En Ruby 1.8 la |x| del argumento del bloque no es local al bloque sino que
es la x de multipliers definida en x = nil.
Obsérvese que la llamada multipliers(2, 3) retorna un array con dos
lambdas.
Obtenemos así un comportamiento inesperado:
$ rvm use 1.8.7 Using /Users/casiano/.rvm/gems/ruby-1.8.7-p352 $ rvm list rvm rubies => ruby-1.8.7-p352 [ i686 ] ruby-1.9.2-head [ x86_64 ] ruby-1.9.2-p290 [ x86_64 ] ruby-1.9.3-head [ x86_64 ] $ ruby closure_shared_variables.rb 6Esto es así porque la única
x contiene el último valor asignado a ella: 3.
En este código el problema desaparece con versiones posteriores a la 1.9 porque los argumentos de un bloque son siempre locales:
$ rvm use 1.9.2 Using /Users/casiano/.rvm/gems/ruby-1.9.2-p290 $ ruby closure_shared_variables.rb 4
Casiano Rodriguez León 2015-01-07