ডো ব্লক বনাম ধনুর্বন্ধনী ব্যবহার করে {}


112

রুবি থেকে নতুন, আপনার নবাগত গ্লোভস লাগান।

নিম্নলিখিত দুটি স্নিপেটের মধ্যে কোনও পার্থক্য (অস্পষ্ট বা বাস্তব)?

my_array = [:uno, :dos, :tres]
my_array.each { |item| 
    puts item
}

my_array = [:uno, :dos, :tres]
my_array.each do |item| 
    puts item
end

আমি বুঝতে পারি ব্রেস সিনট্যাক্স আপনাকে এক লাইনে ব্লক স্থাপন করতে দেয়

my_array.each { |item| puts item }

তবে এর বাইরে কি অন্যের উপর একটি সিনট্যাক্স ব্যবহারের বাধ্যতামূলক কারণ রয়েছে?


5
দুর্দান্ত প্রশ্ন। আমি অভিজ্ঞ রুবিবাদীরা যা পছন্দ করেন তাতে আমি আগ্রহী।
জোনাথন স্টার্লিং




1
আপনি ডও ব্লকের একটি লাইনও লিখতে পারেন যদিও এভাল ("my_array.each do | আইটেম | পটস; এন্ড") এর মতো কিছু করার সময় এটি কেবলমাত্র কার্যকর তবে এটি আইআরবি বা পিসিতে ইওল এবং উদ্ধৃতি চিহ্ন ছাড়াই কাজ করে You যখন এটি পছন্দ করা হয় একটি পরিস্থিতি জুড়ে আসতে পারে। যদিও আমাকে জিজ্ঞাসা করবেন না। এটি তদন্ত করার অন্য একটি বিষয়।
ডগলাস জি। অ্যালেন

উত্তর:


100

রুবি কুকবুক বলছে বন্ধনী সিনট্যাক্সের তুলনায় উচ্চতর অর্ডার রয়েছেdo..end

মনে রাখবেন যে বন্ধনী সিনট্যাক্সের do..end সিনট্যাক্সের চেয়ে উচ্চতর প্রাধান্য রয়েছে। নিম্নলিখিত কোড দুটি স্নিপেট বিবেচনা করুন:

1.upto 3 do |x|
  puts x
end

1.upto 3 { |x| puts x }
# SyntaxError: compile error

দ্বিতীয় উদাহরণ কেবল তখনই কাজ করে যখন বন্ধনী ব্যবহার করা হয়, 1.upto(3) { |x| puts x }


7
আহ, বুঝেছি সুতরাং অগ্রাধিকার আদেশের কারণে আপনি যখন ব্যবহার করবেন, আপনি অতিরিক্ত পরামিতি হিসাবে ব্লকটি অতিক্রম করছেন, কিন্তু যখন আপনি বন্ধনী ব্যবহার করেন তখন আপনি পদ্ধতিটি অনুরোধের ফলাফলগুলির প্রথম প্যারামিটার হিসাবে ব্লকটি পাস করছেন to বাম.
অ্যালান ঝড়

2
আমি প্রায়শই সংক্ষিপ্ত উত্তর পছন্দ করি তবে বিকেডিরের উত্তরটি অনেক বেশি পরিষ্কার।
ইয়াকআউট

70

এটি কিছুটা পুরানো প্রশ্ন তবে আমি {}এবং সম্পর্কে আরও কিছুটা ব্যাখ্যা করার চেষ্টা করতে চাইdo .. end

যেমন আগে বলা হয়

বন্ধনী সিনট্যাক্সের do..end এর চেয়ে বেশি অগ্রাধিকার অর্ডার রয়েছে

তবে কীভাবে এই পার্থক্য করে:

method1 method2 do
  puts "hi"
end

এক্ষেত্রে মেথড 1 কে ব্লকের সাথে ডাকা do..endহবে এবং মেথড 2 আর্গুমেন্ট হিসাবে মেথড 1 এ পাস হবে! যা সমানmethod1(method2){ puts "hi" }

তবে আপনি যদি বলেন

method1 method2{
  puts "hi"
}

তারপরে মেথড 2 ব্লকের সাথে কল করা হবে এবং তারপরে ফিরে আসা মানটি আর্গুমেন্ট হিসাবে মেথড 1 এ পাঠানো হবে। যা সমানmethod1(method2 do puts "hi" end)

def method1(var)
    puts "inside method1"
    puts "method1 arg = #{var}"
    if block_given?
        puts "Block passed to method1"
        yield "method1 block is running"
    else
        puts "No block passed to method1"
    end
end

def method2
    puts"inside method2"
    if block_given?
        puts "Block passed to method2"
        return yield("method2 block is running")
    else
        puts "no block passed to method2"
        return "method2 returned without block"
    end
end

#### test ####

method1 method2 do 
    |x| puts x
end

method1 method2{ 
    |x| puts x
}

#### আউটপুট ####

#inside method2
#no block passed to method2
#inside method1
#method1 arg = method2 returned without block
#Block passed to method1
#method1 block is running

#inside method2
#Block passed to method2
#method2 block is running
#inside method1
#method1 arg = 
#No block passed to method1

39

সাধারণত, {}আপনি যখন কোনও ছোট অপারেশন করছেন তখন কনভেনশনটি ব্যবহার করা হয়, উদাহরণস্বরূপ, কোনও পদ্ধতি কল বা তুলনা ইত্যাদি so সুতরাং এটি সঠিকভাবে বোঝায়:

some_collection.each { |element| puts element }

তবে আপনার যদি কিছু জটিল যুক্তি থাকে যা একাধিক লাইনে যায় তবে ব্যবহার করুন do .. end:

1.upto(10) do |x|
  add_some_num = x + rand(10)
  puts '*' * add_some_num
end

মূলত, এটি নেমে আসে, যদি আপনার ব্লক যুক্তিটি একাধিক লাইনে চলে যায় এবং একই লাইনে লাগানো না যায় তবে ব্যবহার করুন do .. endএবং যদি আপনার ব্লক লজিকটি সহজ এবং কেবল একটি সাধারণ / একক লাইন কোড থাকে তবে ব্যবহার করুন {}


6
আমি মাল্টি-লাইন ব্লকগুলির জন্য do / শেষ ব্যবহারের সাথে একমত, তবে আমি যদি বন্ধের সাথে শেষের দিকে অতিরিক্ত পদ্ধতিগুলি শৃঙ্খলাবদ্ধ করি তবে আমি বন্ধনীগুলি সহ যাব। স্টাইলিস্টিকভাবে আমি {...}। পদ্ধতি ()। পদ্ধতি () ওভার ডু ... এন্ড.মোথডো ()। পদ্ধতিতে পছন্দ করি তবে এটি কেবল আমার হতে পারে।
টিন ম্যান

1
সম্মত, যদিও আমি ব্লকযুক্ত কোনও পদ্ধতির ফলাফলকে একটি অর্থপূর্ণ পরিবর্তনশীলকে নির্ধারিত করতে পছন্দ করি এবং তারপরে তার উপর অন্য পদ্ধতিটি কল করি result_with_some_condition = method{|c| c.do_something || whateever}; result_with_some_condition.another_methodযা এটি একে আরও সহজভাবে বোধগম্য করে তোলে। তবে সাধারণত আমি একটি ট্রেনের ধ্বংস এড়াতাম।
NAS

আমি ভাবছি, কেন এই স্টাইলটি এত জনপ্রিয়। "আমরা সর্বদা এটি এইভাবে করেছি" ব্যতীত এর কি অন্য কোনও কারণ আছে?
আইজিএল

9

রুবির ব্লকগুলির জন্য do endবনাম চয়ন করার জন্য দুটি সাধারণ শৈলী রয়েছে { }:

প্রথম এবং খুব সাধারণ স্টাইলটি রুবেলটি রিলে জনপ্রিয় করেছিলেন এবং এটি একক বনাম বহু-লাইনের একটি সাধারণ নিয়মের উপর ভিত্তি করে:

  • { }একক-লাইন ব্লকের জন্য বন্ধনী ব্যবহার করুন
  • do endমাল্টি-লাইন ব্লকগুলির জন্য ব্যবহার করুন

এটি বোঝা যায় কারণ ডু / এন্ডটি একটি লাইনারে খারাপভাবে পড়ে, তবে মাল্টি-লাইন ব্লকের জন্য, }নিজের লাইনে একটি ক্লোজিং ঝুলিয়ে endরাখা রুবিতে ব্যবহার করা সমস্ত কিছু যেমন মডিউল, শ্রেণি এবং পদ্ধতির সংজ্ঞা ( defইত্যাদি) এর সাথে সামঞ্জস্য নয় inc ।) এবং নিয়ন্ত্রণ কাঠামো (if , while, case, ইত্যাদি)

দ্বিতীয়, কম-ঘন ঘন দেখা শৈলীটি শব্দার্থক হিসাবে পরিচিত, বা " ওয়েইরিচ ধনুর্বন্ধনী " প্রয়াত, মহান রুবিবাদক জিম ওয়েইরিচের প্রস্তাবিত:

  • do endপদ্ধতিগত ব্লকগুলির জন্য ব্যবহার করুন
  • ধনুর্বন্ধনী ব্যবহার করুন { }ক্রিয়ামূলক ব্লকের জন্য ব্যবহার

এর অর্থ হ'ল যখন ব্লকটি তার ফেরতের মূল্যের জন্য মূল্যায়ন করা হয় , তখন এটি {}শৃঙ্খলাবদ্ধ হওয়া উচিত, এবং ধনুর্বন্ধনীগুলি পদ্ধতিতে শৃঙ্খলার জন্য আরও সার্থক করে তোলে।

অন্যদিকে, যখন ব্লকটি তার পার্শ্ব-প্রতিক্রিয়াগুলির জন্য মূল্যায়ন করা হয় , তারপরে রিটার্নের মান কোনও ফল হয় না এবং ব্লকটি কেবল "কিছু করা" হয়, তাই এটি বেঁধে রাখা অর্থহীন নয়।

সিনট্যাক্সের এই পার্থক্যটি ব্লকের মূল্যায়ন সম্পর্কে ভিজ্যুয়াল অর্থ বোঝায়, এবং এর রিটার্নের মানটি আপনার যত্ন নেওয়া উচিত কি না।

উদাহরণস্বরূপ, এখানে প্রতিটি আইটেমের জন্য ব্লকের রিটার্ন মান প্রয়োগ করা হয়:

items.map { |i| i.upcase }

তবে, এখানে এটি ব্লকের রিটার্ন মান ব্যবহার করছে না। এটি প্রক্রিয়াগতভাবে পরিচালনা করছে এবং এটির সাথে একটি পার্শ্ব-প্রতিক্রিয়া করছে:

items.each do |item|
  puts item
end

শব্দার্থক শৈলীর আর একটি সুবিধা হ'ল ব্লকটিতে একটি লাইন যুক্ত হওয়ার কারণে আপনার করণীয় / শেষ করার জন্য ধনুর্বন্ধনী পরিবর্তন করতে হবে না।

পর্যবেক্ষণ হিসাবে, কাকতালীয়ভাবে কার্যকরী ব্লকগুলি প্রায়শই এক-লাইনার এবং প্রক্রিয়াগত ব্লকগুলি (যেমন কনফিগারেশন) বহু-লাইন হয় are সুতরাং, ওয়েইরিচ শৈলী অনুসরণ করে রেলের স্টাইলের মতো প্রায় একই সন্ধান করা শেষ হবে।


1

আমি বছরের পর বছর ধরে ওয়েরিচ স্টাইল ব্যবহার করেছি তবে সর্বদা বন্ধনী ব্যবহার করতে কেবল এ থেকে সরে এসেছি । আমি মনে করি না যে ব্লক শৈলী থেকে তথ্যটি কখনও ব্যবহার করেছি, এবং সংজ্ঞাটি অস্পষ্ট। উদাহরণ স্বরূপ:

date = Timecop.freeze(1.year.ago) { format_date(Time.now) }
customer = Timecop.freeze(1.year.ago) { create(:customer) }

এগুলি কি প্রকৃত বা কার্যক্ষম?

এবং লাইন গণনা জিনিসটি আমার মতে কেবল অকেজো। আমি জানি, 1 বা ততোধিক লাইন রয়েছে কিনা এবং কেন আমি লাইন যুক্ত করেছি বা মুছে ফেলেছি সে কারণেই কেন স্টাইলটি পরিবর্তন করব?

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