Voici Bar#do_things
:
class Bar
def do_things
Foo.some_method(x) do |x|
y = x.do_something
return y_is_bad if y.bad? # how do i tell it to stop and return do_things?
y.do_something_else
end
keep_doing_more_things
end
end
Et voici Foo#some_method
:
class Foo
def self.some_method(targets, &block)
targets.each do |target|
begin
r = yield(target)
rescue
failed << target
end
end
end
end
J'ai pensé à utiliser une relance, mais j'essaie de le rendre générique, donc je ne veux rien mettre de particulier dans Foo
.
Utilisez le mot-clé next
. Si vous ne voulez pas continuer avec l'élément suivant, utilisez break
.
Lorsque next
est utilisé dans un bloc, le bloc se ferme immédiatement, rendant ainsi le contrôle à la méthode itérateur, qui peut alors commencer une nouvelle itération en appelant à nouveau le bloc:
f.each do |line| # Iterate over the lines in file f
next if line[0,1] == "#" # If this line is a comment, go to the next
puts eval(line)
end
Lorsqu'il est utilisé dans un bloc, break
transfère le contrôle du bloc, de l'itérateur qui a appelé le bloc et à la première expression qui suit l'invocation de l'itérateur:
f.each do |line| # Iterate over the lines in file f
break if line == "quit\n" # If this break statement is executed...
puts eval(line)
end
puts "Good bye" # ...then control is transferred here
Et enfin, l'utilisation de return
dans un bloc:
return
provoque toujours le renvoi de la méthode englobante, quelle que soit sa profondeur d'imbrication dans les blocs (sauf dans le cas de lambdas):
def find(array, target)
array.each_with_index do |element,index|
return index if (element == target) # return from find
end
nil # If we didn't find the element, return nil
end
Je voulais juste être capable de sortir d'un bloc - un peu comme un passage en avant, pas vraiment lié à une boucle. En fait, je veux rompre un bloc qui est dans une boucle sans terminer la boucle. Pour ce faire, j'ai fait du bloc une boucle d'une itération:
for b in 1..2 do
puts b
begin
puts 'want this to run'
break
puts 'but not this'
end while false
puts 'also want this to run'
end
J'espère que cela aidera le prochain googleur qui atterrit ici en fonction de la ligne d'objet.
Si vous souhaitez que votre bloc renvoie une valeur utile (par exemple, lorsque vous utilisez #map
, #inject
, etc.), next
et break
acceptent également un argument.
Considérer ce qui suit:
def contrived_example(numbers)
numbers.inject(0) do |count, x|
if x % 3 == 0
count + 2
elsif x.odd?
count + 1
else
count
end
end
end
L'équivalent en utilisant next
:
def contrived_example(numbers)
numbers.inject(0) do |count, x|
next count if x.even?
next (count + 2) if x % 3 == 0
count + 1
end
end
Bien sûr, vous pouvez toujours extraire la logique nécessaire dans une méthode et l'appeler de l'intérieur de votre bloc:
def contrived_example(numbers)
numbers.inject(0) { |count, x| count + extracted_logic(x) }
end
def extracted_logic(x)
return 0 if x.even?
return 2 if x % 3 == 0
1
end
utilisez le mot-clé break
au lieu de return
Vous pouvez peut-être utiliser les méthodes intégrées pour rechercher des éléments particuliers dans un tableau, au lieu de each
ing targets
et tout faire à la main. Quelques exemples:
class Array
def first_frog
detect {|i| i =~ /frog/ }
end
def last_frog
select {|i| i =~ /frog/ }.last
end
end
p ["dog", "cat", "godzilla", "dogfrog", "woot", "catfrog"].first_frog
# => "dogfrog"
p ["hats", "coats"].first_frog
# => nil
p ["houses", "frogcars", "bottles", "superfrogs"].last_frog
# => "superfrogs"
Un exemple serait de faire quelque chose comme ceci:
class Bar
def do_things
Foo.some_method(x) do |i|
# only valid `targets` here, yay.
end
end
end
class Foo
def self.failed
@failed ||= []
end
def self.some_method(targets, &block)
targets.reject {|t| t.do_something.bad? }.each(&block)
end
end
next
et break
semblent bien agir dans cet exemple simplifié!
class Bar
def self.do_things
Foo.some_method(1..10) do |x|
next if x == 2
break if x == 9
print "#{x} "
end
end
end
class Foo
def self.some_method(targets, &block)
targets.each do |target|
begin
r = yield(target)
rescue => x
puts "rescue #{x}"
end
end
end
end
Bar.do_things
sortie: 1 3 4 5 6 7 8