característica de rendimiento de Ruby en relación con la informática
-
11-09-2019 - |
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?
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