রুবি ব্লক এবং ফলন


275

আমি ব্লকগুলি yieldএবং কীভাবে তারা রুবিতে কাজ করে তা বোঝার চেষ্টা করছি ।

কিভাবে yieldব্যবহার করা হয়? অনেকগুলি রেল অ্যাপ্লিকেশন আমি yieldঅদ্ভুত উপায়ে ব্যবহারের দিকে তাকিয়েছি ।

কেউ আমাকে বোঝাতে পারেন বা আমাকে বোঝাতে পারেন যেখানে তাদের বোঝার জন্য যেতে হবে?


2
আপনি কম্পিউটার বিজ্ঞানের সাথে সম্পর্কিত রুবির ফলন বৈশিষ্ট্যের উত্তরে আগ্রহী হতে পারেন । যদিও এটি আপনার চেয়ে কিছুটা আলাদা প্রশ্ন তবে এটি কিছুটা আলোকপাত করতে পারে।
কেন ব্লুম

উত্তর:


393

হ্যাঁ, এটি প্রথমে কিছুটা বিস্মিত।

রুবিতে, পদ্ধতিগুলি কোডের স্বেচ্ছাসেবী বিভাগগুলি সম্পাদন করার জন্য একটি কোড ব্লক পেতে পারে।

যখন কোনও পদ্ধতি কোনও ব্লক প্রত্যাশা করে, তখন এটি yieldফাংশনটি কল করে এটি শুরু করে।

উদাহরণস্বরূপ, তালিকার উপরে পুনরাবৃত্তি করা বা কাস্টম অ্যালগরিদম সরবরাহ করা এটি খুব সহজ।

নিম্নলিখিত উদাহরণটি ধরুন:

আমি Personএকটি নামের সাথে প্রাথমিকভাবে একটি ক্লাস সংজ্ঞায়িত করতে যাচ্ছি , এবং একটি do_with_nameপদ্ধতি সরবরাহ করব যা যখন আহ্বান করা হয়, তখন কেবল nameপ্রাপ্ত বৈশিষ্ট্যের সাথে, অ্যাট্রিবিউটটি পাস করে ।

class Person 
    def initialize( name ) 
         @name = name
    end

    def do_with_name 
        yield( @name ) 
    end
end

এটি আমাদের সেই পদ্ধতিটি কল করতে এবং একটি স্বেচ্ছাসেবীর কোড ব্লক পাস করার অনুমতি দেয়।

উদাহরণস্বরূপ, নামটি মুদ্রণের জন্য আমরা যা করব:

person = Person.new("Oscar")

#invoking the method passing a block
person.do_with_name do |name|
    puts "Hey, his name is #{name}"
end

মুদ্রণ করবে:

Hey, his name is Oscar

লক্ষ্য করুন, ব্লকটি একটি প্যারামিটার হিসাবে, একটি ভেরিয়েবল নামে পরিচিত name(এনবি আপনি এই ভেরিয়েবলটিকে আপনার পছন্দ মতো কোনও কিছু বলতে পারেন, তবে এটি কল করার পক্ষে তা বোঝা যায় name)। কোডটি যখন প্রার্থনা yieldকরে তখন এই পরামিতিটির মান পূরণ করে @name

yield( @name )

ভিন্ন ক্রিয়া সম্পাদনের জন্য আমরা অন্য একটি ব্লক সরবরাহ করতে পারি। উদাহরণস্বরূপ, নামটি বিপরীত করুন:

#variable to hold the name reversed
reversed_name = ""

#invoke the method passing a different block
person.do_with_name do |name| 
    reversed_name = name.reverse
end

puts reversed_name

=> "racsO"

আমরা ঠিক একই পদ্ধতি ( do_with_name) ব্যবহার করেছি - এটি কেবল একটি আলাদা ব্লক।

এই উদাহরণটি তুচ্ছ। আরও আকর্ষণীয় ব্যবহারগুলি হ'ল একটি অ্যারেতে সমস্ত উপাদান ফিল্টার করা:

 days = ["monday", "tuesday", "wednesday", "thursday", "friday"]  

 # select those which start with 't' 
 days.select do | item |
     item.match /^t/
 end

=> ["tuesday", "thursday"]

অথবা, আমরা স্ট্রিং আকারের উপর ভিত্তি করে একটি কাস্টম বাছাই অ্যালগরিদমও সরবরাহ করতে পারি:

 days.sort do |x,y|
    x.size <=> y.size
 end

=> ["monday", "friday", "tuesday", "thursday", "wednesday"]

আমি আশা করি এটি আপনাকে আরও ভাল করে বুঝতে সহায়তা করে।

বিটিডাব্লু, যদি ব্লকটি alচ্ছিক হয় তবে আপনার এটির মতো কল করা উচিত:

yield(value) if block_given?

Alচ্ছিক না হলে কেবল এটির জন্য আবেদন করুন।

সম্পাদনা

@hmak এই উদাহরণগুলির জন্য একটি repl.it তৈরি করেছে: https://repl.it/@makstaks/blocksandyieldsrubyexample


কীভাবে এটি প্রিন্ট racsOহয় the_name = ""
পরিতোষ পিপলেওয়ার

2
দুঃখিত, নামটি একটি উদাহরণের সাথে পরিবর্তনশীল "Oscar" যা এর উত্তরে (উত্তরে খুব পরিষ্কার নয়)
অস্কাররিজ

এই জাতীয় কোড সম্পর্কে কি? person.do_with_name {|string| yield string, something_else }
f.ardelian

7
সুতরাং জাভাস্ক্রিপ্টির ভাষায়, এটি কোনও প্রদত্ত পদ্ধতিতে কলব্যাক পাস করার এবং এটি কল করার একটি মানক উপায়। ব্যাখ্যার জন্য ধন্যবাদ!
yitznewton

আরও সাধারণ উপায়ে - একটি ব্লক কৌশল কৌশল অনুসারে একটি রুবি "বর্ধিত" সিনট্যাক্স চিনি। কারণ সাধারণ ব্যবহার হল অন্যান্য ক্রিয়াকলাপের প্রসঙ্গে কিছু করার জন্য একটি কোড সরবরাহ করা। কিন্তু রুবি উন্নত একটি উপায় যেমন শীতল জিনিস DSLs লেখা যেমন ব্লক ব্যবহার প্রসঙ্গে প্রায় পাস খুলে
রোমান বুলগাকভের

25

রুবিতে, পদ্ধতিগুলি যুক্তিগুলি এমনভাবে ডাকা হয়েছিল কিনা তা পরীক্ষা করে দেখতে পারে যে সাধারণ যুক্তিগুলির পাশাপাশি একটি ব্লক সরবরাহ করা হয়েছিল। সাধারণত এটি block_given?পদ্ধতিটি ব্যবহার করে করা হয় তবে আপনি &চূড়ান্ত যুক্তির নামের আগে একটি অ্যাম্পারস্যান্ড ( ) উপস্থাপন করে সুস্পষ্ট প্রোক হিসাবে ব্লকটি উল্লেখ করতে পারেন ।

যদি কোনও পদ্ধতির কোনও ব্লকের সাথে যুক্ত হয় তবে পদ্ধতিটি yieldপ্রয়োজনে কিছু যুক্তি সহ ব্লককে (ব্লকটিকে কল করতে) নিয়ন্ত্রণ করতে পারে। এই উদাহরণ পদ্ধতিটি যা বিবেচনা করে তা বিবেচনা করুন:

def foo(x)
  puts "OK: called as foo(#{x.inspect})"
  yield("A gift from foo!") if block_given?
end

foo(10)
# OK: called as foo(10)
foo(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as foo(123)
# BLOCK: A gift from foo! How nice =)

বা, বিশেষ ব্লক আর্গুমেন্ট সিনট্যাক্স ব্যবহার করে:

def bar(x, &block)
  puts "OK: called as bar(#{x.inspect})"
  block.call("A gift from bar!") if block
end

bar(10)
# OK: called as bar(10)
bar(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as bar(123)
# BLOCK: A gift from bar! How nice =)

একটি ব্লক ট্রিগার বিভিন্ন উপায় জানতে ভাল।
এলপিং

22

এটি এখানে খুব সম্ভব যে কেউ এখানে সত্যিকারের বিস্তারিত উত্তর সরবরাহ করতে পারে তবে আমি রবার্ট সোসিনস্কির এই পোস্টটি সর্বদা ব্লক, প্রোকস এবং ল্যাম্বডাসের মধ্যে সূক্ষ্মতার এক দুর্দান্ত ব্যাখ্যা হিসাবে খুঁজে পেয়েছি।

আমার যুক্ত করা উচিত যে আমি বিশ্বাস করি যে পোস্টটি আমি সংযুক্ত করছি সেটি রুবি ১.৮ এর সাথে নির্দিষ্ট। কিছু জিনিস রুবি ১.৯ এ পরিবর্তিত হয়েছে যেমন ব্লক ভেরিয়েবলগুলি ব্লকের স্থানীয় হয়। 1.8 এ, আপনি নিম্নলিখিতগুলির মতো কিছু পাবেন:

>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Goodbye"

যেখানে 1.9 আপনাকে দেবে:

>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Hello"

এই মেশিনে আমার 1.9 নেই তাই উপরেরটির এতে কোনও ত্রুটি থাকতে পারে।


এই নিবন্ধটিতে দুর্দান্ত বিবরণ, এটি আমার নিজের থেকে সমস্ত কিছু বের করতে কয়েক মাস লেগেছিল =)
ম্যায়ারিক্স

আমি রাজী. আমি মনে করি না যতক্ষণ না পড়ার আগে পর্যন্ত অর্ধেক জিনিস বুঝিয়েছি।
theiv

আপডেট হওয়া লিঙ্কটি এখন 404। এখানে ওয়েব্যাক মেশিনের লিঙ্ক
ক্লেনওয়েল

@ ক্লেইনওয়েল ধন্যবাদ জানার জন্য, আমি আবার লিঙ্কটি আপডেট করেছি।
দ্য ভিআইভি

13

আপনি ইতিমধ্যে দুর্দান্ত উত্তরে আপনি কেন এমন কাজ করবেন তা আমি বাছাই করতে চাই।

আপনি কোন ভাষা থেকে এসেছেন তা ধারণা নেই, তবে ধরেই নেওয়া এটি একটি স্থির ভাষা, এই ধরণের জিনিসটি আপনাকে পরিচিত দেখাবে। এইভাবে আপনি জাভাতে কোনও ফাইল পড়েন

public class FileInput {

  public static void main(String[] args) {

    File file = new File("C:\\MyFile.txt");
    FileInputStream fis = null;
    BufferedInputStream bis = null;
    DataInputStream dis = null;

    try {
      fis = new FileInputStream(file);

      // Here BufferedInputStream is added for fast reading.
      bis = new BufferedInputStream(fis);
      dis = new DataInputStream(bis);

      // dis.available() returns 0 if the file does not have more lines.
      while (dis.available() != 0) {

      // this statement reads the line from the file and print it to
        // the console.
        System.out.println(dis.readLine());
      }

      // dispose all the resources after using them.
      fis.close();
      bis.close();
      dis.close();

    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

পুরো স্ট্রিম শেইনিং জিনিসটিকে উপেক্ষা করে ধারণাটি হ'ল এটি

  1. পরিষ্কার করা দরকার এমন সংস্থান শুরু করুন
  2. সংস্থান ব্যবহার করুন
  3. এটি পরিষ্কার করা নিশ্চিত করুন

আপনি এটি রুবিতে এটি করেন

File.open("readfile.rb", "r") do |infile|
    while (line = infile.gets)
        puts "#{counter}: #{line}"
        counter = counter + 1
    end
end

বন্যভাবে আলাদা। এটিকে নিচে ভাঙ্গছে

  1. কীভাবে সংস্থানটি শুরু করতে হবে তা ফাইল শ্রেণিকে বলুন
  2. ফাইল ক্লাসটি এর সাথে কী করতে হবে তা বলুন
  3. জবা ছেলেরা যারা এখনও টাইপ করছে তাদের হাসি ;-)

এখানে, এক এবং দুই ধাপ পরিচালনা করার পরিবর্তে, আপনি মূলত এটিকে অন্য শ্রেণিতে অর্পণ করুন। আপনি দেখতে পাচ্ছেন, এটি নাটকীয়ভাবে আপনার কী পরিমাণ কোড লিখতে হবে তা নামিয়ে আনে, যা জিনিসগুলি পড়া সহজ করে তোলে এবং মেমরি ফাঁস, বা ফাইল লকগুলি পরিষ্কার না হওয়ার মতো জিনিসগুলির সম্ভাবনা হ্রাস করে।

এখন, এর মতো নয় যে আপনি জাভাতে অনুরূপ কিছু করতে পারবেন না, আসলে, মানুষ এখন কয়েক দশক ধরে এটি করে আসছে। একে কৌশল প্যাটার্ন বলা হয় । পার্থক্যটি হ'ল ব্লক ছাড়াই, ফাইল উদাহরণের মতো সাধারণ কিছু জন্য, আপনার লেখার জন্য প্রয়োজনীয় ক্লাস এবং পদ্ধতিগুলির পরিমাণের কারণে কৌশল ওভারকিল হয়ে যায়। ব্লক সহ এটি এটি করার একটি সহজ এবং মার্জিত উপায়, এটি আপনার কোডটিকে সেভাবে কাঠামো না দেওয়ার কোনও মানে হয় না।

এটি কেবলমাত্র ব্লকগুলি ব্যবহার করার উপায় নয়, তবে অন্যান্য (যেমন বিল্ডার প্যাটার্নটি, যা আপনি রেলগুলিতে এফআই রূপে দেখতে পারেন) যথেষ্ট পরিমাণে সমান যে এটি একবার আপনার মাথাটি গুটিয়ে ফেললে এটি স্পষ্ট হওয়া উচিত। আপনি যখন ব্লকগুলি দেখেন, তখন এটি ধরে নেওয়া সাধারণভাবে নিরাপদ যে পদ্ধতি কলটি আপনি যা করতে চান তা হ'ল এবং ব্লকটি কীভাবে আপনি এটি করতে চান তা বর্ণনা করছে।


5
আসুন এটি কিছুটা সহজ করুন: File.readlines("readfile.rb").each_with_index do |line, index| puts "#{index + 1}: #{line}" endএবং জাভা লোকগুলিতে আরও শক্ত করে হাসি।
মাইকেল হ্যাম্পটন 4

1
@ মিশেলহ্যাম্পটন, আপনি কয়েক গিগাবাইট দীর্ঘ একটি ফাইল পড়ার পরে হাসবেন।
akostadinov

@akostadinov না ... যে আমাকে কাঁদতে চায়!
মাইকেল হ্যাম্পটন

3
@ মিশেলহ্যাম্পটন বা আরও ভাল: IO.foreach('readfile.rb').each_with_index { |line, index| puts "#{index}: #{line}" }(মেমরির কোনও সমস্যা নেই)
ফান্ড মনিকার লসুইট

12

আমি এই নিবন্ধটি খুব দরকারী বলে মনে করেছি। বিশেষত, নিম্নলিখিত উদাহরণ:

#!/usr/bin/ruby

def test
  yield 5
  puts "You are in the method test"
  yield 100
end

test {|i| puts "You are in the block #{i}"}

test do |i|
    puts "You are in the block #{i}"
end

যা নিম্নলিখিত ফলাফল প্রদান করা উচিত:

You are in the block 5
You are in the method test
You are in the block 100
You are in the block 5
You are in the method test
You are in the block 100

সুতরাং মূলত প্রতিটি সময় yieldরুবিতে কল করা doব্লক বা অভ্যন্তরে কোডটি চালাবে {}। যদি কোনও প্যারামিটার সরবরাহ করা হয় yieldতবে এটি doব্লকের পরামিতি হিসাবে সরবরাহ করা হবে ।

আমার জন্য, এই প্রথম যখন আমি বুঝতে পেরেছিলাম যে doব্লকগুলি কী করছে। এটি মূলত ফাংশনটির অভ্যন্তরীণ ডেটা স্ট্রাকচারগুলিতে অ্যাক্সেস দেওয়ার একটি উপায়, এটি পুনরাবৃত্তির জন্য বা ফাংশনের কনফিগারেশনের জন্য।

সুতরাং রেলগুলি যখন আপনি নিম্নলিখিত লিখুন:

respond_to do |format|
  format.html { render template: "my/view", layout: 'my_layout' }
end

এটি respond_toফাংশনটি পরিচালনা করবে যা do(অভ্যন্তরীণ) formatপ্যারামিটারের সাথে ব্লক দেয় । তারপরে আপনি .htmlএই অভ্যন্তরীণ ভেরিয়েবলে ফাংশনটি কল করুন যা renderকমান্ডটি চালানোর জন্য কোড ব্লক দেয় । দ্রষ্টব্য যে .htmlকেবলমাত্র এটির অনুরোধ করা ফাইল ফর্ম্যাট হলেই ফল পাওয়া যাবে। (প্রযুক্তিগততা: উত্স থেকে আপনি দেখতে পাচ্ছেন এই ফাংশনগুলি আসলে ব্যবহার করে block.callনা তবে কার্যকারিতাটি মূলত একই, আলোচনার জন্য এই প্রশ্নটি দেখুন )) ফাংশনটিকে কিছু সূচনা করার জন্য একটি উপায় সরবরাহ করে তারপরে কলিং কোড থেকে ইনপুট নেওয়া এবং তারপরে প্রয়োজনে প্রসেসিং চালিয়ে যান।yield

বা অন্য কোনও উপায়ে বলা যায়, এটি কোনও ফাংশনের অনুরূপ একটি অনামি ফাংশনটিকে আর্গুমেন্ট হিসাবে গ্রহণ করে এবং তারপরে জাভাস্ক্রিপ্টে কল করে।


8

রুবিতে, একটি ব্লক মূলত কোডের একটি অংশ যা কোনও পদ্ধতিতে পাস এবং কার্যকর করা যেতে পারে। ব্লকগুলি সর্বদা পদ্ধতিগুলির সাথে ব্যবহৃত হয়, যা সাধারণত তাদের ডেটা ফিড করে (যুক্তি হিসাবে)।

ব্লকগুলি রুবি রত্নগুলিতে (রেলগুলি সহ) এবং ভালভাবে লিখিত রুবি কোডে ব্যাপকভাবে ব্যবহৃত হয়। এগুলি বস্তু নয়, সুতরাং ভেরিয়েবলগুলিতে বরাদ্দ করা যায় না।

বেসিক সিনট্যাক্স

একটি ব্লক code} বা do..end দ্বারা সংযুক্ত কোডের একটি অংশ। কনভেনশন অনুসারে, কোঁকড়ানো ব্রেস সিনট্যাক্সটি একক-লাইন ব্লক এবং do..end বাক্য গঠনটি মাল্টি-লাইন ব্লকের জন্য ব্যবহার করা উচিত।

{ # This is a single line block }

do
  # This is a multi-line block
end 

যে কোনও পদ্ধতি অন্তর্নিহিত যুক্তি হিসাবে ব্লক গ্রহণ করতে পারে। একটি পদ্ধতির মধ্যে ফলন বিবৃতি দ্বারা একটি ব্লক কার্যকর করা হয়। প্রাথমিক বাক্য গঠনটি হ'ল:

def meditate
  print "Today we will practice zazen"
  yield # This indicates the method is expecting a block
end 

# We are passing a block as an argument to the meditate method
meditate { print " for 40 minutes." }

Output:
Today we will practice zazen for 40 minutes.

যখন ফলন বিবৃতি পৌঁছে যায়, ধ্যান পদ্ধতিটি ব্লকের উপর নিয়ন্ত্রণ দেয়, ব্লকের মধ্যে কোডটি কার্যকর করা হয় এবং নিয়ন্ত্রণটি পদ্ধতিতে ফিরে আসে, যা ফলন বিবরণের পরে অবিলম্বে সম্পাদন পুনরায় শুরু করে।

যখন কোনও পদ্ধতিতে একটি উত্পাদনের বিবরণ থাকে, কল করার সময় এটি একটি ব্লক পাওয়ার প্রত্যাশা করে। যদি কোনও ব্লক সরবরাহ না করা হয়, ফলন বিবরণী পৌঁছে যাওয়ার পরে একটি ব্যতিক্রম ছুঁড়ে দেওয়া হবে। আমরা ব্লকটিকে alচ্ছিক করতে পারি এবং উত্থাপন থেকে ব্যতিক্রম এড়াতে পারি:

def meditate
  puts "Today we will practice zazen."
  yield if block_given? 
end meditate

Output:
Today we will practice zazen. 

একাধিক ব্লক কোনও পদ্ধতিতে পাস করা সম্ভব নয়। প্রতিটি পদ্ধতি কেবল একটি ব্লক পেতে পারে।

আরও দেখুন: http://www.zenruby.info/2016/04/intr پيداوار-to-blocks-in-ruby.html


এটিই (কেবলমাত্র) উত্তর যা আমাকে সত্যই বুঝতে দেয় যে কী কী অবরুদ্ধ এবং ফলন এবং কীভাবে সেগুলি ব্যবহার করতে হয়।
এরিক ওয়াং

5

আমি মাঝে মাঝে "ফলন" ব্যবহার করি:

def add_to_http
   "http://#{yield}"
end

puts add_to_http { "www.example.com" }
puts add_to_http { "www.victim.com"}

ঠিক আছে কিন্তু কেন ? প্রচুর কারণ রয়েছে যেমন Loggerব্যবহারকারীর প্রয়োজন না পড়লে কারও কোনও কাজ সম্পাদন করতে হবে না। আপনার যদিও আপনার ব্যাখ্যা করা উচিত ...
ইউলিস বিএন

4

ফলনগুলি, এটিকে সহজভাবে বলতে, আপনার তৈরি পদ্ধতিটিকে ব্লকগুলি কল করতে এবং কল করার অনুমতি দিন। ফলন কীওয়ার্ডটি বিশেষত সেই জায়গা যেখানে ব্লকের 'স্টাফ' সম্পাদিত হবে।


1

আমি এখানে দুটি ফলন করতে চাই points প্রথমত, যখন এখানে প্রচুর উত্তরগুলি ফলন ব্যবহার করে এমন একটি পদ্ধতিতে ব্লক পাস করার বিভিন্ন উপায় সম্পর্কে কথা বলছে, আসুন আমরা নিয়ন্ত্রণ প্রবাহ সম্পর্কেও কথা বলি। এটি বিশেষত প্রাসঙ্গিক যেহেতু আপনি কোনও ব্লকে একাধিকবার উপার্জন করতে পারবেন। আসুন একটি উদাহরণ দেখুন:

class Fruit
  attr_accessor :kinds

  def initialize 
    @kinds = %w(orange apple pear banana)
  end

  def each 
    puts 'inside each'
    3.times { yield (@kinds.tap {|kinds| puts "selecting from #{kinds}"} ).sample }
  end  
end

f = Fruit.new
f.each do |kind|
  puts 'inside block'
end    

=> inside each
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block

যখন প্রতিটি পদ্ধতি আহ্বান করা হয়, এটি লাইন দ্বারা লাইন কার্যকর করে। এখন আমরা যখন 3. টাইমস ব্লকে যাব, তখন এই ব্লকটি 3 বার ডাকা হবে। প্রতিবার এটি ফলন প্রার্থনা করে। এই ফলনটি প্রতিটি পদ্ধতির নামক পদ্ধতির সাথে যুক্ত ব্লকের সাথে যুক্ত। এটি লক্ষ্য করা গুরুত্বপূর্ণ যে প্রতিবারের ফলন আহ্বান করা হয়েছে, এটি ক্লায়েন্ট কোডের প্রতিটি পদ্ধতির ব্লকে নিয়ন্ত্রণ ফিরিয়ে দেয়। ব্লকটি সম্পাদন শেষ হয়ে গেলে এটি আবার 3. টাইমস ব্লকে ফিরে আসে। এবং এটি 3 বার ঘটে। সুতরাং ক্লায়েন্ট কোডের সেই ব্লকটি 3 টি পৃথক অনুষ্ঠানে আহ্বান করা হয়েছে, যেহেতু ফলন স্পষ্টত 3 পৃথক বার বলা হয়।

আমার দ্বিতীয় বিষয়টি enum_for এবং ফলন সম্পর্কে। enum_for জন্য Enumerator ক্লাস তাত্ক্ষণিক করে তোলে এবং এই গণকের অবজেক্ট ফলনের জন্যও সাড়া দেয়।

class Fruit
  def initialize
    @kinds = %w(orange apple)
  end

  def kinds
    yield @kinds.shift
    yield @kinds.shift
  end
end

f = Fruit.new
enum = f.to_enum(:kinds)
enum.next
 => "orange" 
enum.next
 => "apple" 

সুতরাং প্রতিবার লক্ষ্য করুন যে আমরা যখন বাহ্যিক পুনরুক্তিকারীর সাথে প্রকারের আবেদন করি তখন এটি একবারে ফলন শুরু করবে। পরের বার যখন আমরা এটি বলব তখন এটি পরবর্তী উত্পাদন এবং আরও কিছুকে ডেকে আনে।

Enum_for এর সাথে একটি আকর্ষণীয় বিড়ম্বনা আছে। ডকুমেন্টেশন অনলাইনে নিম্নলিখিতটি জানিয়েছে:

enum_for(method = :each, *args)  enum
Creates a new Enumerator which will enumerate by calling method on obj, passing args if any.

str = "xyz"
enum = str.enum_for(:each_byte)
enum.each { |b| puts b }    
# => 120
# => 121
# => 122

আপনি যদি enum_for এর জন্য আর্গুমেন্ট হিসাবে কোনও চিহ্ন নির্দিষ্ট না করেন তবে রুবি গ্রাহককে প্রতিটি পদ্ধতিতে গ্রাহককে আবদ্ধ করবে। কিছু ক্লাসে স্ট্রিং ক্লাসের মতো প্রতিটি পদ্ধতি থাকে না।

str = "I like fruit"
enum = str.to_enum
enum.next
=> NoMethodError: undefined method `each' for "I like fruit":String

সুতরাং, enum_for- র সাথে অনুরোধ করা কিছু সামগ্রীর ক্ষেত্রে, আপনাকে অবশ্যই গণনা করার পদ্ধতিটি পরিষ্কার করা উচিত।


0

পদ্ধতিতে কোনও মান ফেরত দেওয়ার জন্য ফলন নামহীন ব্লক হিসাবে ব্যবহার করা যেতে পারে। নিম্নলিখিত কোড বিবেচনা করুন:

Def Up(anarg)
  yield(anarg)
end

আপনি "আপ" একটি পদ্ধতি তৈরি করতে পারেন যা একটি আর্গুমেন্ট বরাদ্দ করা হয়েছে। আপনি এখন এই যুক্তিটি উত্পাদন করার জন্য বরাদ্দ করতে পারেন যা কল করে এবং সম্পর্কিত ব্লক কার্যকর করে। প্যারামিটার তালিকার পরে আপনি ব্লকটি বরাদ্দ করতে পারেন।

Up("Here is a string"){|x| x.reverse!; puts(x)}

যখন আপ পদ্ধতিটি আর্গুমেন্ট সহ ফলনকে কল করে, অনুরোধটি প্রক্রিয়া করার জন্য এটি ব্লক ভেরিয়েবলের কাছে প্রেরণ করা হয়।

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