Pregunta

Recientemente he descubierto bloques de Ruby y características de rendimiento, y me preguntaba: ¿dónde encaja esto en términos de la teoría de la informática? Es una técnica de programación funcional, o algo más específico?

¿Fue útil?

Solución

yield de Ruby no es un iterador como en C # y Python. yield sí es en realidad un concepto muy simple una vez que entienda cómo funcionan los bloques en Ruby.

Sí, los bloques son una característica de la programación funcional, a pesar de que Ruby no es propiamente un lenguaje funcional. De hecho, Ruby utiliza el método lambda para crear objetos de bloque, que es tomado de la sintaxis de Lisp para crear funciones anónimas - que es lo que son los bloques. Desde el punto de vista de la informática, los bloques de Ruby (y las funciones lambda de Lisp) son cierres . En Ruby, métodos suelen tener un solo bloque. (Puede pasar más, pero es difícil.)

La palabra clave yield en Ruby es sólo una forma de llamar a un bloque que se ha dado a un método. Estos dos ejemplos son equivalentes:

def with_log
  output = yield # We're calling our block here with yield
  puts "Returned value is #{output}"
end

def with_log(&stuff_to_do) # the & tells Ruby to convert into
                           # an object without calling lambda
  output = stuff_to_do.call # We're explicitly calling the block here
  puts "Returned value is #{output}"
end

En el primer caso, sólo estamos suponiendo que hay un bloque y decir llamarlo. En la otra, Ruby envuelve el bloque en un objeto y lo pasa como argumento. La primera es más eficiente y fácil de leer, pero son efectivamente la misma. Que se dice ya sea uno como este:

with_log do
  a = 5
  other_num = gets.to_i
  @my_var = a + other_num
end

Y sería imprimir el valor que terminó siendo asignado a @my_var. (OK, así que es una función completamente estúpida, pero creo que se entiende la idea.)

Los bloques se utilizan para muchas cosas en Ruby. Casi todos los lugares que tendría que utilizar un bucle en un lenguaje como Java, es reemplazado en Ruby con métodos que toman bloques. Por ejemplo,

[1,2,3].each {|value| print value} # prints "123"
[1,2,3].map {|value| 2**value}    # returns [2, 4, 8]
[1,2,3].reject {|value| value % 2 == 0} # returns [1, 3]

Como se señaló Andrew, que también se usa comúnmente para abrir archivos y muchos otros lugares. Básicamente cada vez que tenga una función estándar que podría utilizar un poco de lógica personalizada (como ordenar una matriz o procesar un archivo), podrás usar un bloque. Hay otros usos también, pero esta respuesta es ya tanto tiempo me temo que va a causar ataques al corazón en los lectores con las constituciones más débiles. Es de esperar que esto aclare la confusión sobre este tema.

Otros consejos

Hay más para producir bloques y que el simple bucle.

Enumeración enumerables tiene una serie de cosas que puede hacer con enumeraciones, tales como preguntando si una afirmación es cierta para cualquier miembro de un grupo, o si es cierto para todos los miembros, o la búsqueda de cualquiera o todos los miembros de cumplir una determinada condición.

Bloques también son útiles para el alcance variable. En lugar de simplemente ser conveniente, puede ayudar con un buen diseño. Por ejemplo, el código

File.open("filename", "w") do |f|
  f.puts "text"
end

asegura que el flujo de archivos se cierra cuando haya terminado con él, incluso si se produce una excepción, y que la variable está fuera del alcance, una vez que haya terminado con él.

Google informal no vino con un buen post sobre los bloques y los rendimientos en rubí. No sé por qué.

respuesta al comentario

Sospecho que se cierra, por la finalización de bloque, no porque la variable se sale del ámbito.

Mi opinión es que no sucede nada especial cuando la última variable apuntando a un objeto sale del ámbito, además de ese objeto de ser elegible para la recolección de basura. No sé cómo confirmar esto, sin embargo.

puedo demostrar que el objeto de archivo se cierra antes de que llegue basura recogida, que por lo general no sucede inmediatamente. En el siguiente ejemplo, se puede ver que un objeto de archivo se cierra en la segunda sentencia puts, pero no ha sido recogido de basura.

g = nil
File.open("/dev/null") do |f|
  puts f.inspect # #<File:/dev/null>
  puts f.object_id # Some number like 70233884832420
  g = f
end
puts g.inspect # #<File:/dev/null (closed)>
puts g.object_id # The exact same number as the one printed out above,
  # indicating that g points to the exact same object that f pointed to

Creo que la declaración yield originó a partir de la CLU idioma. Siempre me pregunto si el personaje de Tron fue nombrado después de CLU también ....

'corrutina' es la palabra clave que está buscando.

por ejemplo. http://en.wikipedia.org/wiki/Yield

Rendimiento de la informática y ciencias de la información:

  • en informática, un punto de retorno (y re-entrada) de un co-rutina
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top