রুবিতে কি "কর ... যখন" লুপ আছে?


452

আমি এই কোডটি ব্যবহারকারীর নামগুলিতে প্রবেশ করতে দিচ্ছি যখন প্রোগ্রামটি খালি স্ট্রিং প্রবেশ না করা পর্যন্ত তাদের এ্যারে সংরক্ষণ করে (তারা অবশ্যই প্রতিটি নামের পরে এন্টার টিপতে পারে):

people = []
info = 'a' # must fill variable with something, otherwise loop won't execute

while not info.empty?
    info = gets.chomp
    people += [Person.new(info)] if not info.empty?
end

এই কোডটি একটি করণে আরও সুন্দর দেখায় ... লুপ করার সময়:

people = []

do
    info = gets.chomp
    people += [Person.new(info)] if not info.empty?
while not info.empty?

এই কোডে আমাকে কিছু এলোমেলো স্ট্রিংয়ের জন্য তথ্য বরাদ্দ করতে হবে না।

দুর্ভাগ্যক্রমে এই ধরণের লুপটি রুবির মধ্যে উপস্থিত বলে মনে হয় না। কেউ কি আরও ভাল উপায় এটি করার পরামর্শ দিতে পারেন?


1
আমি ভাবি যে লুপটি স্বাভাবিক সময় দেখতে আরও সুন্দর লাগে এবং এটি পড়া সহজ।
Magne

1
@ জেরেমি রুটেনের এমন কোনও সুযোগ রয়েছে যা আপনি সিইই শেনের উত্তরের গ্রহণযোগ্য উত্তর পরিবর্তন করতে আগ্রহী loop do; ...; break if ...; end?
ডেভিড উইনিস্কি

উত্তর:


643

সতর্কতা :

begin <code> end while <condition>রুবি লেখক Matz দ্বারা প্রত্যাখ্যাত হয়। পরিবর্তে তিনি Kernel#loopযেমন ব্যবহারের পরামর্শ দেন

loop do 
  # some code here
  break if <condition>
end 

২৩ নভেম্বর ২০০৫ এ এখানে একটি ইমেল এক্সচেঞ্জ রয়েছে যেখানে ম্যাটজ বলেছেন:

|> Don't use it please.  I'm regretting this feature, and I'd like to
|> remove it in the future if it's possible.
|
|I'm surprised.  What do you regret about it?

Because it's hard for users to tell

  begin <code> end while <cond>

works differently from

  <code> while <cond>

রোসটাটা কোড উইকির একইরকম গল্প রয়েছে:

২০০৫ সালের নভেম্বরে, রুবির নির্মাতা ইউকিহিরো মাতসুমোতো এই লুপটির বৈশিষ্ট্যটির জন্য অনুশোচনা করেছিলেন এবং কার্নেল # লুপটি ব্যবহারের পরামর্শ দিয়েছেন।


18
চিহ্নিত করা. এই begin end whileপদ্ধতিটি সঠিক মনে হয়নি। আমাকে দলের বাকী সবাইকে বোঝানোর জন্য আমাকে চশমা দেওয়ার জন্য ধন্যবাদ।
জোশুয়া পিন্টার

2
দেখে মনে হচ্ছে প্রারম্ভ-শেষে-লুপটি লুপটি চালানোর আগে অবস্থার মূল্যায়ন করছে। এটির ও নিয়মিত লুপের মধ্যে পার্থক্য হ'ল এটি অন্তত একবার চালানোর গ্যারান্টিযুক্ত। সমস্যাটি তৈরি করার সময় এটি করার মতো পর্যাপ্ত পরিমাণ।
ব্যবহারকারী 1992284

4
সুতরাং, যতদূর আমি ভালভাবে বুঝতে পেরেছি, শুরু-শেষে-এ "অনুশোচনা" হয়েছে কারণ সংশোধনকারীদের অর্থবৃত্তিকে লঙ্ঘন করে, এটি: ব্লকটি কার্যকর করার আগে সেগুলি পরীক্ষা করা হয়, উদাহরণস্বরূপ: p রাখে if! K.nil ?. এখানে 'যদি' একটি 'সংশোধক' হয়: এটি 'পূট কে' স্টেটমেন্ট নির্বাহ করে কিনা তা নির্ধারণ করার জন্য এটি আগে পরীক্ষা করা হয়েছিল while এটি যখন / লুপগুলি হয় না (যখন কোনও প্রারম্ভ-শেষে-ব্লকের সংশোধক হিসাবে ব্যবহৃত হয়) !), প্রথম মৃত্যুদণ্ড কার্যকর হওয়ার পরে মূল্যায়ন করা হয় Mআমি এর ফলে আফসোস হয়েছে, তবে আমাদের কোনও পুরানো ফোরামের পোস্টের চেয়ে কিছু 'শক্তিশালী' আছে, যেমন অন্যান্য অনেক অনুষ্ঠানে ব্যবহার করার মতো একটি সরকারী অবমূল্যায়নও রয়েছে?
এগ্রোস্টিনাক্স

2
আমার এই রুবি 'ডু-ওয়েল' লুপটি কেন কাজ করছে না তা বোঝার জন্য আমার বিব্রতকর পরিমাণে সময় লেগেছে। সি-স্টাইলের করণীয়কে আরও ঘনিষ্ঠভাবে নকল করতে আপনার 'যদি না' ব্যবহার করা উচিত, অন্যথায় আপনি আমার মতো শেষ হয়ে যেতে পারেন এবং শর্তটি উল্টাতে ভুলে যেতে পারেন: পি
কনার ক্লার্ক

1
@ জামেস লিঙ্কযুক্ত মেল অনুসারে, তিনি বলেছিলেন যে তিনি এটি যুক্ত করে "অনুশোচনা" করছেন। কখনও কখনও লোকেরা ভাষা ডিজাইনার হলেও ভুল করে।
জিয়াং চিয়ামিয়াভ

188

Tempfile#initializeরুবি কোর লাইব্রেরিতে উত্সটি পড়ার সময় আমি নিম্নলিখিত স্নিপেটটি পেয়েছি :

begin
  tmpname = File.join(tmpdir, make_tmpname(basename, n))
  lock = tmpname + '.lock'
  n += 1
end while @@cleanlist.include?(tmpname) or
  File.exist?(lock) or File.exist?(tmpname)

প্রথম নজরে, আমি ধরে নিয়েছিলাম যে সংশোধনকারীটি শুরু হওয়ার আগে ... সমাপ্তির বিষয়বস্তুর আগে মূল্যায়ন করা হবে, তবে এটি তেমন নয়। পালন:

>> begin
?>   puts "do {} while ()" 
>> end while false
do {} while ()
=> nil

যেমনটি আপনি প্রত্যাশা করেছিলেন, লুপটি কার্যকর হতে থাকবে যখন সংশোধকটি সত্য।

>> n = 3
=> 3
>> begin
?>   puts n
>>   n -= 1
>> end while n > 0
3
2
1
=> nil

যদিও আমি এই প্রতিমাটি আর কখনও না দেখে খুশি হব, শুরু করুন ... শেষটি বেশ শক্তিশালী। নীচে প্যারাম ছাড়াই ওয়ান-লাইন পদ্ধতিটি স্মরণে রাখতে একটি সাধারণ প্রতিমা:

def expensive
  @expensive ||= 2 + 2
end

আরও জটিল কিছু স্মরণ করার জন্য এখানে একটি কুশ্রী, তবে দ্রুত উপায়:

def expensive
  @expensive ||=
    begin
      n = 99
      buf = "" 
      begin
        buf << "#{n} bottles of beer on the wall\n" 
        # ...
        n -= 1
      end while n > 0
      buf << "no more bottles of beer" 
    end
end

মূলত জেরেমি বুরহিস লিখেছেন । সামগ্রীটি এখানে অনুলিপি করা হয়েছে কারণ মনে হয় এটি উত্পন্ন সাইট থেকে সরানো হয়েছে। অনুলিপিগুলি ওয়েব সংরক্ষণাগার এবং রুবি বাজ ফোরামেও পাওয়া যাবে । - টিকটিকিটি বিল করুন



56
এই কারণেই কোনও বাহ্যিক সাইটের সাথে লিঙ্ক করার সময়, আমি সর্বদা আমার উত্তরটিতে প্রাসঙ্গিক তথ্যটি অনুলিপি করে নিশ্চিত করি।
davr

10
আপনি কেন শেষ মুহুর্তের সামগ্রীর শুরু হওয়ার আগেই সংশোধকটির মূল্যায়ন হবে বলে আশা করবেন? এটি সেইভাবেই করা হবে ... ততক্ষণে লুপগুলি কাজ করার কথা। এবং কেন আপনি "এই প্রবাদটি আবার কখনও না দেখে খুশি হবেন?" এতে দোষ কী? আমি বিভ্রান্ত
bergie3000

2
শুরু ... প্রান্তটি একটি ব্লকের মতো দেখায়, একইভাবে {...}} এতে কোনও ভুল নেই।
ভিক্টর পুদেয়েভ

1
-1: সিউই শেনের উত্তর ব্যাখ্যা করে যে begin .. endএটি কিছুটা ভ্রূকুচিভুক্ত। loop do .. break if <condition>পরিবর্তে ব্যবহার করুন।
কেভিন

102

এটার মত:

people = []

begin
  info = gets.chomp
  people += [Person.new(info)] if not info.empty?
end while not info.empty?

তথ্যসূত্র: রুবির লুকানো কাজ {} করার সময় () লুপ


1
হেই, এতে মারধর করা। অভিশাপ।
ব্লারগবার্ড

কোনও ইনপুট না থাকলে এই কোডটি অ্যারেতে একটি খালি স্ট্রিং যুক্ত করবে না?
অ্যান্ড্রুআর

1
যদিও এটি এখানে প্রয়োগ হয় না, প্রারম্ভ-শেষে-নির্মাণের একটি সমস্যা হ'ল, অন্য সমস্ত রুবি নির্মাণের মতো নয়, এটি সর্বশেষ অভিব্যক্তির মানটি ফিরিয়ে দেয় না: "শুরু 1 টি শেষ এবং মিথ্যা" শূন্য প্রদান করে (1 নয়, মিথ্যা নয়)
টোকল্যান্ড

9
আপনি until info.empty?বরং ব্যবহার করতে পারেন while not info.empty?
অ্যান্ড্রু গ্রিম

আসলে @ অ্যান্ড্রুআর সেই ধরণের বিন্দু .. তুলনার আগে জিনিসগুলি করতে .. ডিপ্লে ("অবশিষ্ট = # {গণনা}) করার সময় (গণনা> 0) করুন ... আমি" অবশিষ্ট = 0 "এর একটি প্রদর্শন পেয়েছি .. নিখুঁত!
baash05

45

এ কেমন?

people = []

until (info = gets.chomp).empty?
  people += [Person.new(info)]
end

4
ভাল, আরও মার্জিত।
ব্লারগবার্ড

23
তবে এটি "ডু ... যখন" লুপ নয়। :)
আলেকজান্ডার প্রোকোফিয়েভ

4
তবে এই ক্ষেত্রে এটি একই কাজ করে, যদি না আমার ভুল হয়
ব্লারগবার্ড

18
@ ব্লগারবার্ড, একটি ডু .. লুপ সর্বদা একবার চালায়, তারপরে এটি চালিয়ে যাওয়া উচিত কিনা তা দেখার জন্য মূল্যায়ন করে। একটি traditionalতিহ্যবাহী যখন / অবধি লুপ 0 বার চালাতে পারে। এটি একটি বিশাল পার্থক্য নয়, তবে তারা পৃথক।
স্কট সুইজে

5
@ স্কট, এটি সত্য - আমি কেবল বোঝাতে চেয়েছিলাম যে এই কোডটি অপের সমতুল্য, যদিও এটি কোনও কাজ / সময় ব্যবহার করে না। যদিও সত্যই, এই কোডটি লুপের "কাজ" এর অর্ধেকটি শর্তে করে, সুতরাং এটি লুপাটের সময় প্রচলিত নয় - শর্তটি মেলে না, কিছু কাজ এখনও সম্পন্ন হবে।
ব্লারগবার্ড

11

আমার ব্লগে হাববার্ডারের মৃত লিঙ্ক থেকে সম্পূর্ণ পাঠ্য নিবন্ধটি এখানে।

Tempfile#initializeরুবি কোর লাইব্রেরিতে উত্সটি পড়ার সময় আমি নিম্নলিখিত স্নিপেটটি পেয়েছি :

begin
  tmpname = File.join(tmpdir, make_tmpname(basename, n))
  lock = tmpname + '.lock'
  n += 1
end while @@cleanlist.include?(tmpname) or
  File.exist?(lock) or File.exist?(tmpname)

প্রথম নজরে, আমি ধরে নিয়েছি যে whileসংশোধনকারীটির বিষয়বস্তুর আগে মূল্যায়ন করা হবে begin...end, তবে এটি তেমন নয়। পালন:

>> begin
?>   puts "do {} while ()" 
>> end while false
do {} while ()
=> nil

যেমনটি আপনি প্রত্যাশা করেছিলেন, লুপটি কার্যকর হতে থাকবে যখন সংশোধকটি সত্য।

>> n = 3
=> 3
>> begin
?>   puts n
>>   n -= 1
>> end while n > 0
3
2
1
=> nil

যদিও আমি এই প্রতিমাটি আর কখনও না দেখে খুশি হব, begin...endবেশ শক্তিশালী। নীচে প্যারাম ছাড়াই ওয়ান-লাইন পদ্ধতিটি স্মরণে রাখতে একটি সাধারণ প্রতিমা:

def expensive
  @expensive ||= 2 + 2
end

আরও জটিল কিছু স্মরণ করার জন্য এখানে একটি কুশ্রী, তবে দ্রুত উপায়:

def expensive
  @expensive ||=
    begin
      n = 99
      buf = "" 
      begin
        buf << "#{n} bottles of beer on the wall\n" 
        # ...
        n -= 1
      end while n > 0
      buf << "no more bottles of beer" 
    end
end

10

এটি এখন সঠিকভাবে কাজ করে:

begin
    # statment
end until <condition>

তবে, ভবিষ্যতে এটি মুছে ফেলা হতে পারে, কারণ beginবিবৃতিটি বিপরীত। দেখুন: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/6745

ম্যাটজ (রুবির স্রষ্টা) এটি এইভাবে করার সুপারিশ করেছেন:

loop do
    # ...
    break if <condition>
end

6

আমি যা জড়ো করি তা থেকে ম্যাটজ নির্মাণটি পছন্দ করে না

begin
    <multiple_lines_of_code>
end while <cond>

কারণ, এটি শব্দার্থবিজ্ঞানের চেয়ে আলাদা

<single_line_of_code> while <cond>

এতে প্রথম কনস্ট্রাক্ট শর্তটি যাচাই করার আগে কোডটি প্রথমে কার্যকর করে এবং দ্বিতীয় কনস্ট্রাক্টটি কোডটি কার্যকর করার আগে শর্তটি পরীক্ষা করে (যদি কখনও হয়)। আমি ম্যাটজ দ্বিতীয় কনস্ট্রাক্ট রাখতে পছন্দ করি কারণ এটি যদি বিবৃতিগুলির সাথে একটি লাইন নির্মাণের সাথে মেলে।

আমি বিবৃতি এমনকি জন্য দ্বিতীয় নির্মাণ পছন্দ না। অন্যান্য সমস্ত ক্ষেত্রে কম্পিউটার বাম থেকে ডান কোড নির্বাহ করে (যেমন। || এবং&&) উপরে থেকে নীচে। মানুষেরা নীচে থেকে নীচে বামে থেকে কোড পড়েন।

আমি পরিবর্তে নিম্নলিখিত নির্মাণের পরামর্শ দিই:

if <cond> then <one_line_code>      # matches case-when-then statement

while <cond> then <one_line_code>

<one_line_code> while <cond>

begin <multiple_line_code> end while <cond> # or something similar but left-to-right

আমি জানি না যে এই পরামর্শগুলি বাকী ভাষার সাথে পার্স করবে কিনা। তবে যে কোনও ক্ষেত্রে আমি ভাষার ধারাবাহিকতার পাশাপাশি বাম থেকে ডান সম্পাদনকে অগ্রাধিকার দিচ্ছি।


3
a = 1
while true
  puts a
  a += 1
  break if a > 10
end

3
এটি কিছুটা গোটোর মতো দেখাচ্ছে। কোডটি আপনার উদ্দেশ্যকে অস্পষ্ট করে।
গেরহার্ড

আমার সাথে দুর্দান্ত দেখাচ্ছে, while trueপরিবর্তে প্রতিস্থাপন করা যায় loop do
ডেভিড উইনিস্কি

@ ডেভিডওয়িনিস্কি, সত্যিই, while trueপ্রতিস্থাপন করা যেতে পারে loop do। তবে আমি উভয় নির্মাণকে লুপের অভ্যন্তরে প্রচুর পুনরাবৃত্তির সাথে পরীক্ষা করেছি এবং আবিষ্কার করেছি যে এর চেয়ে while trueকমপক্ষে 2x দ্রুতloop do । পার্থক্যটি ব্যাখ্যা করতে পারি না, তবে এটি অবশ্যই আছে। (কোড 2017, দিন 15 এর আগমন পরীক্ষা করার সময়
আবিষ্কৃত হয়েছে

2

এখানে অন্য একটি:

people = []
1.times do
  info = gets.chomp
  unless info.empty? 
    people += [Person.new(info)]
    redo
  end
end

আমি একে একে unlessএকে অগ্রাধিকার হিসাবে অগ্রাধিকার দিচ্ছি এবং কেবল unlessশেষে একটি 'ঝুঁকির' সন্ধান করার জন্য আমি একগুচ্ছ কোডের (যা এখানে দেখানোর চেয়ে আরও বেশি কিছু হতে পারে) মাধ্যমে পড়ি না । কোডে এটি একটি সাধারণ নীতি যা পরিবর্তককারীরা এবং শর্তগুলি ব্যবহার করা সহজতর যখন তারা 'সামনে' থাকে।
মাইকেল ডুরান্ট

আমি মাঝে মাঝে চাই যে কোডারদের প্রতিটি অতিরিক্ত তুলনার জন্য নগদ দিতে হয়েছিল। এবং এটি আমাদের কাছে এটি কীভাবে "দেখায়" এটি কীভাবে যে জিনিসটিতে এটি প্রতিদিন ব্যবহার করে যা মিলিয়ন বার ব্যবহার করে তার চেয়ে কম গুরুত্বপূর্ণ ছিল।
baash05

-3
ppl = []
while (input=gets.chomp)
 if !input.empty?
  ppl << input
 else
 p ppl; puts "Goodbye"; break
 end
end

2
এটি কিছুটা গোটোর মতো দেখাচ্ছে। কোডটি আপনার উদ্দেশ্যকে অবিচ্ছিন্ন করে দেয় এবং দেখতে খুব খারাপ লাগে।
জেরহার্ড

বিস্মৃত * অপ্রচলিত নয়।
qedk
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.