রুবি ব্লক থেকে কীভাবে বেরোন?


419

এখানে 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

উত্তর:


747

কীওয়ার্ডটি ব্যবহার করুন 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

2
ধন্যবাদ, তবে পরবর্তী কেবল অ্যারেতে পরবর্তী আইটেমটিতে চলে আসে। এটি কি প্রস্থান করা সম্ভব?
ব্যবহারকারী169930

আপনাকে রিটার্ন মান সহ পরবর্তী কল করতে হবে। "ডিফ এফ; এক্স = ফলন; এক্স রাখে; শেষ" "এফ পরের ৩ করুন;" ও "রাখেন; কনসোলে এই প্রিন্ট 3 (তবে" ও "নয়) রাখে।
মার্সেল জ্যাকওয়ার্থ

5
next, break, return, আপনি তুলনা করতে পারবেন না
finiteloop

আমি @ মার্সেলজ্যাকওয়ার্থ মন্তব্যে nextবা breakযুক্তি যুক্ত সম্পর্কে যুক্ত করা মন্তব্যে একটি উত্তর যুক্ত করেছি ।
টাইলার হলিয়েন

8
এখানে একটি কীওয়ার্ডও বলা হয়েছে redo, যা মূলত কেবলমাত্র কার্যকর সম্পাদনটি বর্তমান পুনরাবৃত্তির মধ্যে দিয়ে ব্লকের শীর্ষে ফিরে যায়।
আজেদী 32

59

আমি কেবল একটি ব্লকটি ভেঙে ফেলতে সক্ষম হতে চাই - লুপের সাথে সম্পর্কিত না, ফরোয়ার্ড গোটোর মতো সাজানো really আসলে, আমি লুপটি বন্ধ না করে একটি লুপে থাকা একটি ব্লকটি ভাঙ্গতে চাই। এটি করতে, আমি ব্লকটিকে একটি-পুনরাবৃত্তি লুপ করেছি:

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

আশা করি এটি পরবর্তী গুগলারের সাথে সাবজেক্ট লাইনের উপর ভিত্তি করে এখানে অবতরণ করেছে helps


4
এটি ছিল কেবলমাত্র প্রতিক্রিয়া যা প্রশ্নের উত্তর দেওয়া হয়েছিল answered আরও পয়েন্ট প্রাপ্য। ধন্যবাদ।
অ্যালেক্স নায়ে

এটি বিরতি এবং পরবর্তী উভয়ের জন্য একই কাজ করে। যদি মিথ্যাটিকে সত্যে পরিবর্তন করা হয় তবে পরবর্তী চেহারাতে থাকবে এবং বিরতি ছড়িয়ে যাবে।
জি। অ্যালেন মরিস তৃতীয়

39

আপনি আপনার ব্লক একটি দরকারী মান (যেমন যখন ব্যবহার ফিরতে চান #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

1
যুক্তি সহ ইঙ্গিতটির জন্য ধন্যবাদ break!
rkallensee

2
আপনি দয়া করে w / একটি নির্দিষ্ট উদাহরণ ব্যবহার করে আপডেট করতে পারেন break(সম্ভবত আপনার nextbreak
মাইক গ্রাফ

একটি খুব আকর্ষণীয় জিনিস। break somethingকাজ করে, break(something)কাজ করে তবে true && break(somehting)একটি সিনট্যাক্স ত্রুটি দেয়। শুধু এফওয়াইআই। যদি শর্ত প্রয়োজন হয়, তবে ifবা unlessব্যবহার করা দরকার।
akostadinov

21

breakপরিবর্তে কীওয়ার্ডটি ব্যবহার করুনreturn


8

সম্ভবত আপনি ব্যবহার করতে পারেন বিল্ট-ইন একটি অ্যারের মধ্যে নিদিষ্ট আইটেমগুলিকে খোঁজার পরিবর্তে জন্য পদ্ধতি each-ing 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

2
অ্যারে শ্রেণিতে এর মতো স্বেচ্ছাসেবী পদ্ধতি যুক্ত করবেন না! এটা সত্যিই খারাপ অভ্যাস।
mrbrdo

3
রেল এটা করে, তাহলে সে কেন পারবে না?
wberry

2
@ উবেরি এটি যে এটি করা উচিত তা বলার অপেক্ষা রাখে না । ;) সাধারণভাবে, যদিও আপনার কাছে বেশ ভাল কারণ না থাকলে বানরের প্যাচিং কোর ক্লাসগুলি এড়ানো ভাল best (অর্থাত্ বেশ কয়েকটি কার্যকর সাধারণকরণযোগ্য কার্যকারিতা যুক্ত করা যা অন্যান্য কোডগুলি প্রচুর পরিমাণে কার্যকর খুঁজে পাবে)। তারপরেও, হালকাভাবে পদচারণ করুন কারণ একবার যখন কোনও শ্রেণি ভারী বাঁদর দ্বারা জড়িত হয়ে যায়, গ্রন্থাগারগুলির পক্ষে একে অপরের উপর দিয়ে হাঁটা শুরু করা এবং কিছু চরম বেআইনী আচরণ সৃষ্টি করা সহজ।
blm768

2

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


2
বিরতি অবিলম্বে শেষ হয় - পরবর্তী পরবর্তী পুনরাবৃত্তি অবিরত।
বেন অউবিন

-3

রুবি ব্লক থেকে বেরিয়ে আসার জন্য returnকীওয়ার্ডটি ব্যবহার করুনreturn if value.nil?


2
returnফাংশন থেকে প্রস্থান করবেন না ?
রেজারডল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.