programing

루비 블록에서 탈출하는 방법은?

skycolor 2023. 6. 1. 22:37
반응형

루비 블록에서 탈출하는 방법은?

여기 있습니다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

그리고 여기 있습니다.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

인상을 사용하려고 생각했지만, 일반적으로 만들려고 노력하고 있기 때문에 특정한 것을 넣고 싶지 않습니다.Foo.

키워드 사용next다음 항목으로 계속 진행하지 않으려면 다음을 사용합니다.break.

언제next를 사용하면 블록이 즉시 종료되고 제어가 반복기 메서드로 되돌아갑니다. 그러면 다시 블록을 호출하여 새 반복을 시작할 수 있습니다.

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

블록에서 사용할 경우,break는 컨트롤을 블록 밖으로, 블록을 호출한 반복기 밖으로, 반복기 호출 후 첫 번째 식으로 전송합니다.

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

그리고 마지막으로, 의 사용법은return블록 내:

return블록 내에 얼마나 깊이 내포되어 있는지에 관계없이 항상 둘러싸는 방법을 반환합니다(람다의 경우 제외).

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

저는 단지 블록을 뚫고 나갈 수 있기를 원했습니다. 일종의 전진처럼 말이죠. 루프와 관련이 없습니다.사실, 저는 루프를 종료하지 않고 루프에 있는 블록을 절단하고 싶습니다.이를 위해 블록을 1회 반복 루프로 만들었습니다.

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

이것이 주제 라인을 기반으로 여기에 도착하는 다음 구글러에게 도움이 되기를 바랍니다.

블록이 유용한 값을 반환하도록 하려면(예: 사용 시)#map,#inject등),next그리고.break인수도 수락합니다.

다음 사항을 고려합니다.

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

동등한 용도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

물론 필요한 논리를 항상 메서드에 추출하여 블록 내부에서 호출할 수 있습니다.

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

키워드를 사용합니다.break대신에return

아마도 당신은 배열에서 특정한 항목을 찾기 위해 내장된 메소드를 사용할 수 있을 것입니다.each-잉targets손으로 모든 것을 하는 것.몇 가지 예:

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"

한 가지 예로 다음과 같은 작업을 수행할 수 있습니다.

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그리고.break이 단순화된 예에서 옳은 일을 하는 것처럼 보입니다!

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

출력: 1 3 4 5 6 7 8

스택을 '비 예외적'인 방법으로 풀 수 있는 네 가지 방법이 있습니다.next,break,return,그리고.throw.

next블록이 반환됩니다.

break블록에 양보한 메서드가 반환됩니다.

return블록이 정의된 메서드를 반환합니다.

throw다음을 찾을 때까지 스택을 가로질러 이동합니다.catch일치하는 기호와 함께, 그리고 그것을 되돌립니다.이는 예외적이지 않은 상황에 대한 '경량' 예외와 매우 유사합니다.

이들은 모두 정상적으로 반환되는 마지막 식 값 대신 반환되는 반환 값을 취할 수 있습니다.

다음은 몇 가지 예입니다.

def doSomething
  puts "> doSomething"
  yield
  puts "< doSomething"
end

def withNext
  puts "> withNext"
  doSomething do
    puts "> block"
    puts "* NEXT! causes the block to return to doSomething"
    next
    puts "< block"
  end
  puts "< withNext"
end

def withBreak
  puts "> withBreak"
  doSomething do
    puts "> block"
    puts "* BREAK! causes doSomething to return to withBreak"
    break
    puts "< block"
  end
  puts "< withBreak"
end

def withReturn
  puts "> withReturn"
  doSomething do
    puts "> block"
    puts "* RETURN! causes withReturn to return"
    return
    puts "< block"
  end
  puts "< withReturn"
end

def withThrow
  puts "> withThrow"
  catch :label do
    puts "> catch :label"
    doSomething do
      puts "> block 1"
      doSomething do
        puts "> block 2"
        puts "* THROW! causes catch :label to return to withThrow"
        throw :label
        puts "< block 2"
      end
      puts "< block 1"
    end
    puts "< catch :label"
  end
  puts "< withThrow"
end

withNext
puts "* Done"
puts
withBreak
puts "* Done"
puts
withReturn
puts "* Done"
puts
withThrow
puts "* Done"

출력:

> withNext
> doSomething
> block
* NEXT! causes the block to return to doSomething
< doSomething
< withNext
* Done

> withBreak
> doSomething
> block
* BREAK! causes doSomething to return to withBreak
< withBreak
* Done

> withReturn
> doSomething
> block
* RETURN! causes withReturn to return
* Done

> withThrow
> catch :label
> doSomething
> block 1
> doSomething
> block 2
* THROW! causes catch :label to return to withThrow
< withThrow
* Done

루비 블록에서 벗어나려면 키워드를 사용하면 됩니다. next.

  • next람다, 블럭 또는 procit가 들어 있는 것을 종료합니다.
  • break블록에 양보하거나 블록이 있는 프로세서 람다를 호출한 메서드를 종료합니다.

신용 대상: 루비 블록 반환, 중단, 다음

언급URL : https://stackoverflow.com/questions/1402757/how-to-break-out-from-a-ruby-block

반응형