কম্পিউটার টিউটোরিয়াল

রুবি ব্লক, প্রক এবং ল্যাম্বডা: একটি বিস্তারিত গাইড

রুবি ব্লক, প্রক এবং ল্যাম্বডা।

এগুলো কী?

এগুলো কীভাবে কাজ করে?

এগুলো একে অপরের থেকে কীভাবে আলাদা?

এই পোস্ট পড়ে আপনি সেটা এবং আরও অনেক কিছু শিখবেন!

সামগ্রী

  • ১ রুবি ব্লক বোঝা
  • ২ রুবি Yield কীওয়ার্ড
  • ৩ ইমপ্লিসিট vs এক্সপ্লিসিট ব্লক
  • ৪ ব্লক দেওয়া হয়েছে কিনা চেক করা
  • ৫ ল্যাম্বডা কী?
  • ৬ ল্যাম্বডা vs প্রক
  • ৭ ক্লোজার
  • ৮ Binding ক্লাস
  • ৯ ভিডিও টিউটোরিয়াল
  • ১০ সমাপ্তি
    • ১০.১ রিলেটেড

রুবি ব্লক বোঝা

রুবি ব্লক ছোট বেনামী ফাংশন যেগুলো মেথডে পাস করা যায়।

ব্লকগুলো do / end স্টেটমেন্ট বা ব্র্যাকেট {} এর মাঝপথে এনক্লোজ করা থাকে, এবং এগুলো একাধিক আর্গুমেন্ট নিতে পারে।

আর্গুমেন্টের নামগুলো দুটি পাইপ | ক্যারেক্টারের মাঝপথে ডিফাইন করা হয়।

আপনি যদি আগে each ব্যবহার করে থাকেন তবে আপনি ইতিমধ্যে ব্লক ব্যবহার করেছেন!

এখানে একটি উদাহরণ:

 # ফর্ম ১: সিঙ্গল লাইন ব্লকের জন্য রিকমেন্ডেড [1, 2, 3].each { |num| puts num } ^^^^^ ^^^^^^^^ block block arguments body 
 # ফর্ম ২: মাল্টি-লাইন ব্লকের জন্য রিকমেন্ডেড [1, 2, 3].each do |num| puts num end 

একটি রুবি ব্লক উপকারী কারণ এটি আপনাকে কিছু লজিক (কোড) সংরক্ষণ করতে এবং পরে ব্যবহার করতে দেয়।

এটি কীচু হয়তে পারে যেমন ফাইলে ডেটা লেখা, চেক করা একটি এলিমেন্ট অন্যটির সমান কিনা, বা এমনকি একটি এরর মেসেজ প্রিন্ট করা।

রুবি Yield কীওয়ার্ড

রুবিতে yield মানে কী?

Yield হল একটি রুবি কীওয়ার্ড যা একটি ব্লক কল করে যখন আপনি এটি ব্যবহার করেন।

এটি হলো মেথডগুলো ব্লক কীভাবে ব্যবহার করে!

আপনি যখন yield কীওয়ার্ড ব্যবহার করেন, ব্লকের ভেতরের কোড রান করবে এবং তার কাজ করবে।

সাদা একটি রেগুলার রুবি মেথড কল করার মতো।

এখানে একটি উদাহরণ:

 def print_once yield end print_once { puts "Block is being run" } 

এটি print_once-এ পাস করা যেকোনো ব্লক রান করে, ফলস্বরূপ "Block is being run" স্ক্রিনে প্রিন্ট হবে।

আপনি কি জানতেন…

yield একাধিকবার ব্যবহার করা যায়?

আপনি যতবার yield কল করবেন, ব্লকটি ততবার রান করবে, যেন একই মেথড আবার কল করা হয়।

উদাহরণ:

 def print_twice yield yield end print_twice { puts "Hello" } # "Hello" # "Hello" 

এবং মেথডের মতো…

আপনি yield-এ যেকোনো সংখ্যক আর্গুমেন্ট পাস করতে পারেন।

উদাহরণ:

 def one_two_three yield 1 yield 2 yield 3 end one_two_three { |number| puts number * 10 } # 10, 20, 30 

এই আর্গুমেন্টগুলো ব্লকের আর্গুমেন্ট হয়ে যায়।

এই উদাহরণে number।

ইমপ্লিসিট vs এক্সপ্লিসিট ব্লক

ব্লকগুলো হতে পারে “ইমপ্লিসিট” বা “এক্সপ্লিসিট”।

এক্সপ্লিসিট মানে আপনি আপনার প্যারামিটার লিস্টে এটিকে একটি নাম দেন।

আপনি একটি এক্সপ্লিসিট ব্লক অন্য মেথডে পাস করতে পারেন বা একটি ভেরিয়েবলে সেভ করে রাখতে পারেন পরে ব্যবহার করার জন্য।

এখানে একটি উদাহরণ:

 def explicit_block(&block) block.call # same as yield end explicit_block { puts "Explicit block called" } 

&block প্যারামিটারে লক্ষ্য করুন…

এটিই হলো ব্লকের নাম ডিফাইন করার পদ্ধতি!

ব্লক দেওয়া হয়েছে কিনা চেক করা

আপনি যদি ব্লক ছাড়া yield করার চেষ্টা করেন তবে আপনি একটি no block given (yield) এরর পাবেন।

আপনি block_given? মেথড দিয়ে চেক করতে পারেন কোনো ব্লক পাস করা হয়েছে কিনা।

উদাহরণ:

 def do_something_with_block return "No block given" unless block_given? yield end 

এটি এরর প্রতিরোধ করে যদি কেউ আপনার মেথডকে ব্লক ছাড়া কল করে।

ল্যাম্বডা কী?

এক ল্যাম্বডা হলো একটি ব্লক এবং এর প্যারামিটার ডিফাইন করার একটি স্পেশাল সিনট্যাক্স।

আপনি এই ল্যাম্বডাকে একটি ভেরিয়েবলে সেভ করে রাখতে পারেন পরে ব্যবহার করার জন্য।

রুবি ল্যাম্বডা ডিফাইন করার সিনট্যাক্স এমন দেখায়:

 say_something = -> { puts "This is a lambda" } 

আপনি বিকল্প সিনট্যাক্সও ব্যবহার করতে পারেন: -> বদলে lambda।

একটি ল্যাম্বডা ডিফাইন করলে এর ভেতরের কোড রান হবে না, ঠিক যেমন একটি মেথড ডিফাইন করলে মেথডটি রান হয় না, আপনাকে এর জন্য call মেথড ব্যবহার করতে হবে।

উদাহরণ:

 say_something = -> { puts "This is a lambda" } say_something.call # "This is a lambda" 

lambda কল করার অন্যান্য পদ্ধতিও রয়েছে, সেগুলো জানা ভালো, তবে আমি ক্লারিটির জন্য call-এর সাথে থাকার পরামর্শ দিচ্ছি।

লিস্টটি এখানে:

 my_lambda = -> { puts "Lambda called" } my_lambda.call my_lambda.() my_lambda[] my_lambda.=== 

ল্যাম্বডা আর্গুমেন্টও নিতে পারে, এখানে একটি উদাহরণ:

 times_two = ->(x) { x * 2 } times_two.call(10) # 20 

আপনি যদি ল্যাম্বডাকে ভুল সংখ্যক আর্গুমেন্ট পাস করেন তবে এটি এক্সেপশন থ্রো করবে, ঠিক একটি রেগুলার মেথডের মতো।

ল্যাম্বডা vs প্রক

প্রক একটি খুব সিমিলার কনসেপ্ট…

বিভিন্নতা একটি হলো আপনি এগুলো কীভাবে তৈরি করেন।

উদাহরণ:

 my_proc = Proc.new { |x| puts x } 

কোনো ডেডিকেটেড Lambda ক্লাস নেই। একটি lambda শুধু একটি স্পেশাল Proc অবজেক্ট। আপনি যদি Proc-এর ইনস্ট্যান্স মেথডগুলো দেখেন তবে লক্ষ্য করবেন এতে একটি lambda? মেথড রয়েছে।

এখন:

একটি প্রক ল্যাম্বডার থেকে আলাদা ভাবে বیهেভ করে, বিশেষ করে আর্গুমেন্টের বিষয়ে:

 t = Proc.new { |x,y| puts "I don't care about arguments!" } t.call # "I don't care about arguments!" 

procs এবং lambdas-এর মধ্যে আরেকটি বড় পার্থক্য হলো সেগুলো return স্টেটমেন্টের প্রতি কীভাবে রিয়্যাক্ট করে।

একটি lambda নরমালি return করবে, যেন একটি রেগুলার মেথড।

কিন্তু একটি proc করেন্ট কনটেক্সট থেকে return করার চেষ্টা করবে।

আমার মানে কী:

আপনি যদি নিচের কোড রান করেন, তবে আপনি লক্ষ্য করবেন proc কীভাবে LocalJumpError এক্সেপশন থ্রো করে।

কারণ হলো আপনি টপ-লেভেল কনটেক্সট থেকে return করতে পারবেন না।

এটি ট্রাই করুন:

 # কাজ করা উচিত my_lambda = -> { return 1 } puts "Lambda result: #{my_lambda.call}" # এক্সেপশন থ্রো করবে my_proc = Proc.new { return 1 } puts "Proc result: #{my_proc.call}" 

যদি proc একটি মেথডের ভেতরে থাকে, তবে return কল করা সেই মেথড থেকে রিটার্ন করার সমান।

এটি নিচের উদাহরণে ডেমোন্স্ট্রেট করা হয়েছে।

 def call_proc puts "Before proc" my_proc = Proc.new { return 2 } my_proc.call puts "After proc" end p call_proc # Prints "Before proc" but not "After proc" 

procs এবং lambdas কীভাবে আলাদা তার একটি সামারি:

  • ল্যাম্বডা ডিফাইন হয় -> {} দিয়ে এবং প্রক Proc.new {} দিয়ে।
  • প্রক করেন্ট মেথড থেকে রিটার্ন করে, যখন ল্যাম্বডা ল্যাম্বডা থেকে রিটার্ন করে।
  • প্রক আর্গুমেন্টের সঠিক সংখ্যা নিয়ে চিন্তা করে না, যখন ল্যাম্বডা এক্সেপশন থ্রো করবে।

এই লিস্টটি দেখলে আমরা বুঝতে পারি lambdas একটি রেগুলার মেথডের চেয়ে অনেক বেশি ক্লোজ, procs চেয়ে।

ক্লোজার

রুবি প্রক এবং ল্যাম্বডার আরেকটি স্পেশাল এট্রিবিউট রয়েছে। আপনি যখন একটি রুবি প্রক তৈরি করেন, এটি করেন্ট এক্সিকিউশন স্কোপ ক্যাপচার করে রাখে।

এই কনসেপ্ট, যাকে কখনো কখনো ক্লোজার বলা হয়, মানে একটি proc তার সাথে লোকাল ভেরিয়েবল এবং মেথডের মতো ভ্যালু নিয়ে চলবে যেখানে এটি ডিফাইন করা হয়েছিল।

তারা আসল ভ্যালু নয়, বরং একটি রেফারেন্স নিয়ে চলে, তাই যদি ভেরিয়েবলগুলো প্রক তৈরি হওয়ার পর পরিবর্তন হয়, প্রকটি সবসময় লেটেস্ট ভার্সন পাবে।

একটি উদাহরণ দেখি:

 def call_proc(my_proc) count = 500 my_proc.call end count = 1 my_proc = Proc.new { puts count } p call_proc(my_proc) # এটি কী প্রিন্ট করবে? 

এই উদাহরণে আমাদের একটি লোকাল count ভেরিয়েবল রয়েছে, যা 1 সেট করা আছে।

আমাদের একটি প্রকও রয়েছে my_proc নামে, এবং একটি call_proc মেথড যা যেকোনো প্রক বা ল্যাম্বডা রান করে ( call মেথডের মাধ্যমে) যা আর্গুমেন্ট হিসেবে পাস করা হয়েছে।

আপনি কী মনে করেন এই প্রোগ্রামটি কী প্রিন্ট করবে?

লগ হলো 500 সবচেয়ে লজিক্যাল, কিন্তু ‘ক্লোজার’ ইফেক্টের কারণে এটি 1 প্রিন্ট করবে।

এটি হয় কারণ প্রকটি count-এর ভ্যালু ব্যবহার করছে সেখান থেকে যেখানে প্রকটি ডিফাইন করা হয়েছিল, এবং সেটি মেথড ডেফিনিশনের বাইরে।

Binding ক্লাস

রুবি প্রক এবং ল্যাম্বডা এই স্কোপ ইনফরমেশন কোথায় স্টোর করে?

আপনাকে Binding ক্লাস সম্পর্কে বলি…

আপনি যখন binding মেথডের মাধ্যমে একটি Binding অবজেক্ট তৈরি করেন, আপনি কোডের এই পয়েন্টে একটি ‘অ্যাঙ্কর’ তৈরি করছেন।

এই পয়েন্টে ডিফাইন করা সকল ভেরিয়েবল, মেথড এবং ক্লাস পরে এই অবজেক্টের মাধ্যমে উপলব্ধ থাকবে, এমনকি আপনি যদি সম্পূর্ণ ভিন্ন স্কোপে থাকেন।

উদাহরণ:

 def return_binding foo = 100 binding end # Foo উপলব্ধ আছে বাইন্ডিংর কারণে, # এমনকি আমরা সেই মেথডের বাইরে থাকি # যেখানে এটি ডিফাইন করা হয়েছিল। puts return_binding.class puts return_binding.eval('foo') # আপনি যদি সরাসরি foo প্রিন্ট করার চেষ্টা করেন তবে আপনি এরর পাবেন। # কারণ foo মেথডের বাইরে কখনো ডিফাইন করা হয়নি। puts foo 

অন্য কথায়, একটি binding অবজেক্টের কনটেক্সটে কিছু এক্সিকিউট করা একই যেন সেই কোডটি সেখানে ছিল যেখানে সেই binding ডিফাইন করা হয়েছিল ( ‘অ্যাঙ্কর’ মেটাফর মনে রাখুন)।

আপনাকে সরাসরি binding অবজেক্ট ব্যবহার করতে হবে না, কিন্তু এটা জানা ভালো যে এটি একটি জিনিস 🙂

ভিডিও টিউটোরিয়াল

সমাপ্তি

এই পোস্টে আপনি শিখেছেন ব্লক কীভাবে কাজ করে, রুবি প্রক এবং ল্যাম্বডার পার্থক্য এবং আপনি ব্লক তৈরি করার সময় হোয়া ‘ক্লোজার’ ইফেক্ট সম্পর্কে।

একটি জিনিস আমি কভার করিনি वो হলো curry মেথড।

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

আপনি আংশিক সংখ্যক আর্গুমেন্ট পাস করলে আপনি একটি নতুন প্রক পাবেন যেখানে এই আর্গুমেন্টগুলো ইতিমধ্যে ‘প্রি-লোডেড’, যখন সকল আর্গুমেন্ট দেয়া হবে তখন প্রকটি এক্সিকিউট হবে।

আশা করি আপনি এই পোস্টটি এনজয় করেছেন!

নিচের ফর্মে সাবস্ক্রাইব করা এবং বন্ধুদের সাথে শেয়ার করা ভুলবেন না 🙂


  1. ম্যাকে সাফারি কাস্টমাইজ করার 얼টিমেট গাইড

  2. Windows 7 থেকে Ubuntu-এ মাইগ্রেশন: চরম গাইড

  3. PC-এ WhatsApp Web ব্যবহার: চরম গাইড

  4. ম্যাকে Android Messages ব্যবহার করার পূর্ণাঙ্গ ধাপে ধাপে গাইড