Pourquoi l'instruction break dans ruby se comporte-t-elle différemment lors de l'utilisation de Proc.new v. Le signe esperluette?

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

  •  29-10-2019
  •  | 
  •  

Question

L'instruction break pour les blocs (selon " Le programme est défini comme suit "

cela fait revenir le bloc à son itérateur et l'itérateur à retourner à la méthode qui l'a appelé.

Par conséquent, lorsque le code suivant est exécuté, il en résulte une 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

Bien que le code suivant ne lève pas une erreur LocalJumpError. Quelle est la particularité du signe esperluette? L'esperluette n'utilise-t-elle pas implicitement 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 d'autres termes, je lis le signe esperluette comme un moyen d'insérer l'appel Proc.new. À ce stade, le comportement doit être exactement le même que celui du premier extrait de code.

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

: Je suis un nouvel apprentissage de la langue (ruby 1.9.2), et j'apprécierai donc les références et un synopsis détaillé.

Était-ce utile?

La solution

break rend le bloc et l ' appelant du bloc de retour.Dans le code suivant:

proc = Proc.new { break }

L '"appelant" du bloc converti en objet Proc est Proc.new.break est censé faire revenir l'appelant du bloc, mais Proc.new est déjà retourné.

Dans ce code:

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

L'appelant du bloc est iterator, donc il renvoie iterator.

Autres conseils

Voici la réponse .

Ampersand est utilisé pour convertir un proc en bloc et un bloc en proc.

J'ai changé l'exemple pour le mettre en relation avec votre cas:

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

Comme vous pouvez le voir, il n'a pas atteint le "proc après"

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>'

Dans votre deuxième exemple, vous avez un proc in result, le proc rompt avec iterator et retourne à la fonction test.

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

Cela a à voir avec la différence entre les blocs, les procs et les lambdas - et leurs portées respectives.

J'ai écrit un article à ce sujet en 2009 que vous pourriez trouver utile: http://www.leonardoborges.com/writings/2009/07/22/procs-lambdas-blocks-whats-the-difference/

J'espère que cela vous aidera.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top