¿Por qué la declaración de descanso en Ruby se comporta de manera diferente cuando se usa Proc.New v. El signo de ampers y?

StackOverflow https://stackoverflow.com/questions/8888958

  •  29-10-2019
  •  | 
  •  

Pregunta

La declaración de descanso para bloques (según El lenguaje de programación de Ruby) se define de la siguiente manera:

Hace que el bloque regrese a su iterador y al iterador para volver al método que lo invocó.

Por lo tanto, cuando se ejecuta el siguiente código, resulta en un localJumperror.

def test
    puts "entering test method"
    proc = Proc.new { puts "entering proc"; break }
    proc.call # LocalJumpError: iterator has already returned
    puts "exiting test method"
end
test

Mientras que el siguiente código no es Lanza un local Jumperror. ¿Qué tiene de especial el signo de Amperands? ¿No usa implícitamente el signo de Ampers y Proc.New?

def iterator(&proc)
    puts "entering iterator"
    proc.call # invoke the proc
    puts "exiting iterator" # Never executed if the proc breaks
end

def test
    iterator { puts "entering proc"; break }
end
test

En otras palabras, leí el signo de Amperandand como un medio para encender la llamada de Proc.Nnew. En ese momento el comportamiento debe ser el mismo que el primer fragmento de código.

def iterator (p = Proc.new { puts "entering proc"; break})
...
end

Descargo de responsabilidad: Estoy aprendiendo el idioma (Ruby 1.9.2) y, por lo tanto, apreciaré las referencias y una sinopsis detallada.

¿Fue útil?

Solución

break Hace el bloque y la llamador del retorno del bloque. En el siguiente código:

proc = Proc.new { break }

La "persona que llama" del bloque que se convierte en un objeto PROC es PROC.NEW. break Se supone que debe hacer que la persona que llama del bloque regrese, pero Proc.New ya ha regresado.

En este código:

def iterator(&b); b.call; end
iterator { break }

La persona que llama del bloque es iterator, así que hace iterator devolver.

Otros consejos

Aquí esta la responder.

Ampersand se usa para convertir un proceso a un bloque y un bloque a un proc.

Cambié el ejemplo para relacionarme con su caso:

def run_my_code(&my_code)
 puts 'before proc'
 my_code.call
 puts 'after proc'
end
run_my_code { puts "passing a block, accepting a proc"; break}
=> before proc
   passing a block, accepting a proc

Como puede ver, no llegó al 'después de Proc'

def run_my_code
 yield
end
my_proc = Proc.new  { puts "passing a proc instead of block"; break}
run_my_code &my_proc
=> passing a proc instead of block
   LocalJumpError: break from proc-closure
   from (pry):75:in `block in <main>'

En su segundo ejemplo tiene un proceso en resultado, el proceso se rompe de iterator y vuelve a test función.

def iterator(&proc)
  puts 'entering iterator'
  proc.call
  puts 'exiting iterator'
end

def test
  puts 'before test'
  iterator { puts 'entering proc'; break }
  puts 'after test'
end

=>before test
entering iterator
entering proc
after test

Tiene que ver con la diferencia entre bloques, procs y lambdas, y sus respectivos ámbitos.

Escribí una publicación al respecto en 2009 que puede encontrar útil: http://www.leonardoborges.com/writings/2009/07/22/procs-lambdas-blocks-whats-tiferference/

Espero que esto ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top