ruby return proc-object

ruby - ¿Por qué el retorno explícito hace una diferencia en un proceso?



return proc-object (3)

Esta es la semántica para Proc s; No es necesariamente la semántica de todos los bloques. Estoy de acuerdo, esto es un poco confuso. Está ahí para mayor flexibilidad (y quizás en parte porque Ruby no tiene especificaciones, excepto por su implementación).

El comportamiento se define en la implementación de Proc . Lambda comportan de manera diferente, por lo que si desea que su return no salga del método de cierre , use las lambdas . O bien, omita la palabra clave de return de su Proc .

Una investigación profunda de los cierres de Rubys está aquí . Es una exposición fantástica.

Asi que:

def foo f = Proc.new { p2 = Proc.new { return "inner proc"}; p2.call return "proc" } f.call return "foo" end def foo2 result = Proc.new{"proc"}.call "foo2 (proc result is: #{result})" end def bar l = lambda { return "lambda" } result = l.call return "bar (lambda result is: #{result})" end puts foo # inner proc puts foo2 # foo (proc result is: proc) puts bar # bar (lambda result is: lambda)

def foo f = Proc.new { return "return from foo from inside proc" } f.call # control leaves foo here return "return from foo" end def bar b = Proc.new { "return from bar from inside proc" } b.call # control leaves bar here return "return from bar" end puts foo # prints "return from foo from inside proc" puts bar # prints "return from bar"

Pensé que la palabra clave return era opcional en Ruby y que siempre la está return , ya sea que la solicite o no. Teniendo en cuenta esto, me sorprende que foo y bar tengan una salida diferente determinada por el hecho de que foo contiene un return explícito en Proc f .

¿Alguien sabe por qué este es el caso?


Piénselo de esta manera: Proc.new simplemente crea un bloque de código que forma parte de la función de llamada. proc / lambda crea una función anónima que tiene enlaces especiales. Unos pequeños ejemplos de código ayudarán:

def foo f = Proc.new { return "return from foo from inside Proc.new" } f.call # control leaves foo here return "return from foo" end

es equivalente a

def foo begin return "return from foo from inside begin/end" } end return "return from foo" end

así que está claro que la devolución solo regresará de la función ''foo''

a diferencia de:

def foo f = proc { return "return from foo from inside proc" } f.call # control stasy in foo here return "return from foo" end

es equivalente a (ignorando los enlaces ya que no se utiliza en este ejemplo):

def unonymous_proc return "return from foo from inside proc" end def foo unonymous_proc() return "return from foo" end

Lo cual es tan claro que no volverá de foo y continuará con la siguiente declaración.


Ruby tiene tres construcciones:

  1. Un bloque no es un objeto y se crea mediante { ... } o do ... end .
  2. Un proc es un objeto Proc creado por Proc.new o proc .
  3. Un lambda es un Proc creado por lambda (o proc en Ruby 1.8).

Ruby tiene tres palabras clave que regresan de algo:

  1. return termina el método o lambda en que se encuentra.
  2. next termina el bloque, proc o lambda en el que se encuentra.
  3. break termina el método que cedió al bloque o invocó el proc o lambda en el que se encuentra.

En las lambdas, el return comporta como el next , por el motivo que sea. next y break se denominan como están porque se usan más comúnmente con métodos como each , donde la terminación del bloque hará que la iteración se reanude con el siguiente elemento de la colección, y la terminación de each hará que salga del bucle .

Si usas return dentro de la definición de foo , regresarás de foo , incluso si está dentro de un bloque o un proc. Para regresar de un bloque, puede usar la next palabra clave en su lugar.

def foo f = Proc.new { next "return from foo from inside proc" } f.call # control leaves foo here return "return from foo" end puts foo # prints "return from foo"