ফাইবার এমন একটি জিনিস যা আপনি সম্ভবত সরাসরি অ্যাপ্লিকেশন-স্তরের কোডটিতে ব্যবহার করবেন না। এগুলি একটি ফ্লো-কন্ট্রোল আদিম যা আপনি অন্য বিমূর্ততা তৈরি করতে ব্যবহার করতে পারেন, যা আপনি তারপরে উচ্চ-স্তরের কোডে ব্যবহার করেন।
সম্ভবত রুবির # 1 টি ফাইবারের ব্যবহারটি Enumerator
এস প্রয়োগ করতে হয় , যা রুবি ১.৯ এর মূল রুবি শ্রেণি। এগুলি অবিশ্বাস্যরূপে দরকারী।
রুবি ১.৯-এ, আপনি যদি কোনও ক্লাস ছাড়াই মূল ক্লাসগুলিতে প্রায় কোনও পুনরুক্তি পদ্ধতিতে কল করেন তবে এটি একটি ফিরে আসবে Enumerator
।
irb(main):001:0> [1,2,3].reverse_each
=> #<Enumerator: [1, 2, 3]:reverse_each>
irb(main):002:0> "abc".chars
=> #<Enumerator: "abc":chars>
irb(main):003:0> 1.upto(10)
=> #<Enumerator: 1:upto(10)>
এই Enumerator
গুলি প্রচুর পরিমাণে অবজেক্টস এবং তাদের each
পদ্ধতিগুলি এমন উপাদান দেয় যা মূল পুনরুক্তি পদ্ধতি দ্বারা উত্পাদিত হত, যদি এটি একটি ব্লক দিয়ে ডাকা হত। আমি যে উদাহরণটি দিয়েছি, উদাহরণস্বরূপ, এনুমরেটর ফিরে এসেছে reverse_each
এমন একটি each
পদ্ধতি রয়েছে যা 3,2,1 আয় করে। গণক chars
"গ", "খ", "ক" (এবং আরও) উপার্জন দ্বারা ফিরে এসেছিল । তবে, আসল পুনরুক্তি পদ্ধতির বিপরীতে, যদি আপনি next
বারবার ফোন করেন তবে গণকও উপাদানগুলির একে অপরকে ফিরিয়ে দিতে পারে:
irb(main):001:0> e = "abc".chars
=> #<Enumerator: "abc":chars>
irb(main):002:0> e.next
=> "a"
irb(main):003:0> e.next
=> "b"
irb(main):004:0> e.next
=> "c"
আপনি "অভ্যন্তরীণ পুনরাবৃত্তি" এবং "বহিরাগত পুনরাবৃত্তকারী" শুনেছেন (উভয়ের একটি ভাল বর্ণনা "গ্যাং অফ ফোর" ডিজাইন প্যাটার্নসের বইয়ে দেওয়া হয়েছে)। উপরের উদাহরণটি দেখায় যে অভ্যন্তরীণ পুনরাবৃত্তিকে একটি বাহ্যিক ক্ষেত্রে রূপান্তর করতে এনুমারেটর ব্যবহার করা যেতে পারে।
এটি আপনার নিজের গণক তৈরির এক উপায়:
class SomeClass
def an_iterator
# note the 'return enum_for...' pattern; it's very useful
# enum_for is an Object method
# so even for iterators which don't return an Enumerator when called
# with no block, you can easily get one by calling 'enum_for'
return enum_for(:an_iterator) if not block_given?
yield 1
yield 2
yield 3
end
end
চল এটা চেষ্টা করি:
e = SomeClass.new.an_iterator
e.next # => 1
e.next # => 2
e.next # => 3
এক মিনিট অপেক্ষা করুন ... সেখানে কি কিছু অদ্ভুত লাগছে? আপনি স্ট্রেট-লাইন কোড হিসাবে yield
বিবৃতি লিখেছিলেন an_iterator
, তবে গণক সেগুলি একবারে চালাতে পারে । কল করার মধ্যবর্তী সময়ে next
, কার্যকর করা an_iterator
হ'ল "হিমশীতল"। প্রতিবার আপনি যখন কল next
করবেন তখন নীচের yield
বিবৃতিটিতে চলছে এবং তারপরে আবার "হিমশীতল" হয়ে যায়।
আপনি কী অনুমান করতে পারেন এটি কীভাবে বাস্তবায়িত হয়? গণক an_iterator
একটি ফাইবারের সাথে কলটি গুটিয়ে রাখে এবং একটি ব্লক পাস করে যা ফাইবারকে স্থগিত করে । সুতরাং প্রতিবারে an_iterator
ব্লকের ফলন, এটিতে যে ফাইবারটি চলছে তা স্থগিত করা হয়েছে এবং মূল থ্রেডে কার্যকর করা অব্যাহত রয়েছে। পরবর্তী বার আপনি যখন কল next
করবেন তখন এটি ফাইবারের নিয়ন্ত্রণে চলে যায়, ব্লকটি ফিরে আসে এবং an_iterator
যেখানেই ছেড়ে যায় সেখানেই তা চালিয়ে যায়।
তন্তু ছাড়া এটি করার জন্য কী প্রয়োজন হবে তা ভেবে শিক্ষণীয় হবে। প্রতিটি শ্রেণি যা অভ্যন্তরীণ এবং বাহ্যিক উভয় পুনরাবৃত্তিকে সরবরাহ করতে চেয়েছিল তাদের কাছে কলগুলির মধ্যে রাষ্ট্রের ট্র্যাক রাখতে স্পষ্ট কোড থাকতে হবে next
। পরবর্তী প্রতিটি কলকে সেই অবস্থাটি পরীক্ষা করতে হবে এবং কোনও মান ফেরত দেওয়ার আগে এটি আপডেট করতে হবে। ফাইবারের সাহায্যে আমরা কোনও অভ্যন্তরীণ পুনরুক্তিকে স্বয়ংক্রিয়ভাবে একটি বাহ্যিক রূপান্তর করতে পারি।
এই তন্তু দিয়ে persay যা করতে হবে না, কিন্তু আমাকে আরও একটি জিনিস আপনি তথ্যসংগ্রহকারী করতে পারেন উল্লেখ: তারা আপনি ছাড়া অন্য অন্য iterators উচ্চতর-অর্ডার গণনীয় পদ্ধতি প্রয়োগ করা যায় each
। সেটা ভাবুন: সাধারনত সব গণনীয় পদ্ধতি, সহ map
, select
, include?
, inject
, ইত্যাদি, সব উপাদানে কাজ হল each
। কিন্তু যদি কোনও জিনিসের বাইরে অন্য আইট্রেটার থাকে তবে কী হবে each
?
irb(main):001:0> "Hello".chars.select { |c| c =~ /[A-Z]/ }
=> ["H"]
irb(main):002:0> "Hello".bytes.sort
=> [72, 101, 108, 108, 111]
কোনও ব্লক ছাড়াই পুনরাবৃত্তিকারীকে কল করা একজন এনিউরেটরকে রিটার্ন দেয় এবং তারপরে আপনি সেইটিতে অন্যান্য গণ্য পদ্ধতিতে কল করতে পারেন।
ফাইবারের দিকে ফিরে take
যাচ্ছেন , আপনি কি গণনার থেকে পদ্ধতিটি ব্যবহার করেছেন ?
class InfiniteSeries
include Enumerable
def each
i = 0
loop { yield(i += 1) }
end
end
যদি কিছু সেই each
পদ্ধতিটিকে কল করে তবে মনে হয় এটি কখনও ফিরে আসবে না, তাই না? এটা দেখ:
InfiniteSeries.new.take(10) # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
আমি জানি না এটি হুডের নীচে তন্তু ব্যবহার করে কিনা, তবে তা পারে। আঁশগুলি অসীম তালিকাগুলি এবং একটি সিরিজের অলস মূল্যায়ন কার্যকর করতে ব্যবহার করা যেতে পারে। গণকের সাথে সংজ্ঞায়িত কিছু অলস পদ্ধতির উদাহরণের জন্য, আমি এখানে কিছু সংজ্ঞায়িত করেছি: https://github.com/alexdowad/showcase/blob/master/ruby-core/collections.rb
আপনি ফাইবার ব্যবহার করে একটি সাধারণ-উদ্দেশ্যে কর্টিন সুবিধা তৈরি করতে পারেন। আমি এখনও আমার কোনও প্রোগ্রামে কর্টিন ব্যবহার করি নি, তবে এটি জানা ভাল ধারণা।
আমি আশা করি এটি আপনাকে সম্ভাবনার বিষয়ে কিছু ধারণা দেয়। আমি প্রথমদিকে যেমন বলেছিলাম, তন্তুগুলি নিম্ন-স্তরের প্রবাহ-নিয়ন্ত্রণ আদিম। তারা আপনার প্রোগ্রামের মধ্যে একাধিক নিয়ন্ত্রণ-প্রবাহ "অবস্থানগুলি" বজায় রাখা সম্ভব করে তোলে (কোনও বইয়ের পৃষ্ঠাগুলিতে "বিভিন্ন" বুকমার্কগুলির মত)) এবং তাদের মধ্যে পছন্দসই পরিবর্তন করতে পারে। যেহেতু নির্বিচারে কোডটি একটি ফাইবারে চলতে পারে, তাই আপনি একটি ফাইবারের উপর তৃতীয় পক্ষের কোডে কল করতে পারেন এবং তারপরে এটি "হিমায়িত" করতে পারেন এবং যখন এটি আপনার নিয়ন্ত্রণের কোডটিতে ফিরে আসে তখন অন্য কিছু করা চালিয়ে যেতে পারেন।
এরকম কিছু কল্পনা করুন: আপনি একটি সার্ভার প্রোগ্রাম লিখছেন যা অনেক ক্লায়েন্টকে সহায়তা করবে। ক্লায়েন্টের সাথে একটি সম্পূর্ণ মিথস্ক্রিয়াটি বিভিন্ন পদক্ষেপের মধ্য দিয়ে যাওয়ার সাথে জড়িত, তবে প্রতিটি সংযোগ ক্ষণস্থায়ী এবং সংযোগের মধ্যে প্রতিটি ক্লায়েন্টের জন্য আপনাকে রাষ্ট্রের কথা মনে রাখতে হবে। (ওয়েব প্রোগ্রামিংয়ের মতো শব্দ?)
রাষ্ট্রটি স্পষ্টভাবে সংরক্ষণ করে, এবং প্রতি ক্লায়েন্টের সাথে সংযুক্ত হওয়ার পরে এটি পরীক্ষা করার পরিবর্তে (তাদের পরবর্তী "পদক্ষেপ" কী করতে হবে তা দেখার জন্য), আপনি প্রতিটি ক্লায়েন্টের জন্য একটি ফাইবার বজায় রাখতে পারেন। ক্লায়েন্ট সনাক্ত করার পরে, আপনি তাদের ফাইবারটি পুনরুদ্ধার করতে এবং এটি পুনরায় শুরু করতে পারেন। তারপরে প্রতিটি সংযোগের শেষে, আপনি ফাইবারটি স্থগিত করে আবার স্টোর করবেন। এই পদ্ধতিতে, আপনি সমস্ত পদক্ষেপ সহ (সম্পূর্ণরূপে যদি আপনার প্রোগ্রামটি স্থানীয়ভাবে চালানো হয় তবে আপনি স্বাভাবিকভাবেই চান) সম্পূর্ণ মিথস্ক্রিয়াটির জন্য সমস্ত যুক্তি বাস্তবায়নের জন্য আপনি সরল-লাইন কোড লিখতে পারেন।
আমি নিশ্চিত যে এ জাতীয় জিনিস ব্যবহারিক না হওয়ার কারণগুলির অনেকগুলি কারণ রয়েছে (কমপক্ষে আপাতত) তবে আবার আমি আপনাকে সম্ভাবনার কয়েকটি দেখানোর চেষ্টা করছি। কে জানে; একবার আপনি ধারণাটি পেয়ে গেলে আপনি কিছু সম্পূর্ণ নতুন অ্যাপ্লিকেশন নিয়ে আসতে পারেন যা অন্য কেউ এখনও ভাবেনি!