2011-04-24 17 views
13

En mi viaje de mil líneas de Ruby, estoy teniendo un momento muy difícil con el concepto de funciones anónimas. Wikipedia says something about hay un alma anónima en el código y se somete a un orden superior, pero mi entendimiento termina ahí.¿Qué son exactamente las funciones anónimas?

O, en otras palabras, ¿cómo podría (cuando lo entiendo) explicar funciones anónimas a mi madre?

+0

Es "función anónima", un término utilizado con mayor frecuencia en la comunidad Perl? –

+0

Y la comunidad javascript. Y los llamarías expresiones lambda en lisp/scheme. – 0112

Respuesta

14

una función anónima tiene estas características:

  1. no tiene nombre (de ahí el anonimato)
  2. Se define en línea
  3. Se usa cuando no desea que la sobrecarga/formalidad de una función normal
  4. no se hace referencia explícita más de una vez, a menos que pasa como argumento a otra función
+1

¿Podría explicar a qué se refiere con _ "no se hace referencia explícita más de una vez" _? No me parece correcto. Por ejemplo: 'x = lambda {...}; def bar (y); @ opts = {callback: y}; fin; bar (x) 'Ahora hay dos referencias a la función, y podría ser fácilmente tres si' bar' crea cierres. ¿Por qué sugieres que estas referencias de alguna manera hagan que esta lambda ya no sea una 'función anónima'? – Phrogz

+0

¿Podría explicar a qué se refiere con _ "se define en línea" _? ¿Qué sería un ejemplo de algo que no está "definido en línea" _ (pero que coincide con sus otros criterios) que lo convierte en una "función anónima" _? – Phrogz

+0

En línea, quiero decir usar la función anónima como argumento o definirla en el cuerpo de otra función, etc. No en línea sería una función típica. – sym3tri

4

Así como Wikipedia dice: una función sin nombre.

Significa que no puede invocar la función de la manera típica, utilizando su nombre y parámetros. Más bien, la función en sí misma suele ser un parámetro de otra función. Una función que opera en funciones se denomina "función de orden superior".

Considere este JavaScript (Sé que este etiquetado ruby ​​pero ...):

window.onload=function(){ 
      //some code here 
    } 

La función se ejecutará cuando se carga la página, pero no se puede invocar por su nombre, ya que no tiene una nombre.

+2

+1 Además, como preguntas sobre ruby, las funciones anónimas de ruby ​​se llaman lambdas. – Spyros

+0

... o bloques, o procs. – Phrogz

12

Aquí hay una ex amplia de una función anónima en Ruby (llamado un bloque en este caso):

my_array.each{ |item| puts item } 

¿Dónde está la función anónima en el anterior? Por qué, es el que recibe un único parámetro, lo nombra 'artículo' y luego lo imprime. En JavaScript, lo anterior puede escribirse como ...

Array.prototype.each = function(anon){ 
    for (var i=0,len=this.length;i<len;++i) anon(this[i]); 
}; 
myArray.each(function(item){ console.log(item); }); 

... el que tanto hace que sea un poco más claro que una función se pasa como argumento, y también ayuda a apreciar la sintaxis de Ruby . :)

Aquí es otra función anónima (de vuelta en Rubí):

def count_to(n) 
    puts "I'm going to count to #{n}" 
    count = lambda do |i| 
    if (i>0) 
     count[i-1] 
     puts i 
    end 
    end 
    count[n] 
    puts "I'm done counting!" 
end 
count_to(3) 
#=> I'm going to count to 3 
#=> 1 
#=> 2 
#=> 3 
#=> I'm done counting! 

Aunque el ejemplo es obviamente artificial, que muestra cómo se puede crear una nueva función (en este caso llamado recuento) y asignar a una variable, y usar eso para llamadas recursivas dentro de un método maestro. (Algunos creen que esto es mejor que crear un segundo método solo para la recursión, o reutilizar el método maestro para la recursión con parámetros muy diferentes).

La función no tiene nombre, la variable sí. Podría asignarlo a cualquier cantidad de variables, todas con diferentes nombres.

Volviendo al primer ejemplo, hay incluso una sintaxis en Ruby para hacer pasar un lambda como el solo, bloque bendito:

print_it = lambda{ |item| puts item } 
%w[a b c].each(&print_it) 
#=> a 
#=> b 
#=> c 

... pero también se puede pasar una lambda como un parámetro normal y llamada más tarde, como se ilustra aquí:

module Enumerable 
    def do_both_to_each(f1, f2) 
    each do |item| 
     f1[item] 
     f2[item] 
    end 
    end 
end 

print_prefix = lambda{ |i| print "#{i}*#{i} -> " } 
print_squared = lambda{ |i| puts i*i } 

(1..4).do_both_to_each(print_prefix,print_squared) 
#=> 1*1 -> 1 
#=> 2*2 -> 4 
#=> 3*3 -> 9 
#=> 4*4 -> 16 
6

En la adicción a las respuestas anteriores, las funciones anónimas son muy útiles cuando se trabaja con closures:

def make_adder n 
    lambda { |x| 
    x + n 
    } 
end 

t = make_adder 100 
puts t.call 1 

O (en Ruby 1.9):

def make_adder_1_9 n 
    ->(x) { 
    x + n 
    } 
end 

t_1_9 = make_adder_1_9 100 
puts t_1_9.call 1 
+3

En su ejemplo 1.9, también podría usar el azucar de sintaxis para 'llamar':' t_1_9. (1) '. –

+2

... en 1.8 y 1.9 lambdas también pueden invocarse a través de 't_1_9 [1]' _ (que es más corto que ''call' o'.() 'Y, en mi opinión, más estético) _. – Phrogz

Cuestiones relacionadas