রুবি ১.৮-তে, একদিকে প্র্যাক / ল্যাম্বডার মধ্যে এবং অন্যদিকে সূক্ষ্ম পার্থক্য রয়েছে Proc.new
।
- এই পার্থক্য কি?
- কোনটি বেছে নেবেন সে সম্পর্কে কীভাবে আপনি গাইডলাইন দিতে পারেন?
- রুবি ১.৯-এ, প্রোক এবং ল্যাম্বদা পৃথক। চুক্তিটি কি ছিল?
রুবি ১.৮-তে, একদিকে প্র্যাক / ল্যাম্বডার মধ্যে এবং অন্যদিকে সূক্ষ্ম পার্থক্য রয়েছে Proc.new
।
উত্তর:
তৈরি করা lambda
এবং এর সাথে তৈরি করা প্রক্সের মধ্যে আরেকটি গুরুত্বপূর্ণ তবে সূক্ষ্ম পার্থক্য হ'ল Proc.new
তারা কীভাবে return
বিবৃতিটি পরিচালনা করে :
lambda
ক্র্যাক্টেড প্রোকে, return
বিবৃতিটি কেবল প্রাক থেকে পাওয়া যায়Proc.new
ক্র্যাকড প্রোকে, return
বিবৃতিটি আরও খানিকটা আশ্চর্যজনক: এটি কেবল প্রোক থেকে নয়, প্র্যাকটি ঘেরানো পদ্ধতি থেকেও নিয়ন্ত্রণ ফিরিয়ে দেয়!এখানে lambda
-created proc এর return
ক্রিয়াটি। এটি এমনভাবে আচরণ করে যা আপনি সম্ভবত আশা করেন:
def whowouldwin
mylambda = lambda {return "Freddy"}
mylambda.call
# mylambda gets called and returns "Freddy", and execution
# continues on the next line
return "Jason"
end
whowouldwin
#=> "Jason"
এখন এখানে একটি Proc.new
ক্রিয়েটেড প্রোক return
একই কাজ করছে। আপনি সেই ক্ষেত্রে একটি দেখতে পাচ্ছেন যেখানে রুবি সবচেয়ে স্বল্প বিস্ময়ের নীতিটি ভেঙে দিয়েছে:
def whowouldwin2
myproc = Proc.new {return "Freddy"}
myproc.call
# myproc gets called and returns "Freddy",
# but also returns control from whowhouldwin2!
# The line below *never* gets executed.
return "Jason"
end
whowouldwin2
#=> "Freddy"
এই বিস্ময়কর আচরণের জন্য ধন্যবাদ (পাশাপাশি কম টাইপিং), আমি প্রস তৈরি lambda
করার Proc.new
সময় ওভার ব্যবহারের পক্ষে পছন্দ করি।
proc
পদ্ধতিও রয়েছে। এটি কি কেবল একটি সংক্ষিপ্ত হাতের জন্য Proc.new
?
proc
সমতূল্যProc.new
proc
পছন্দ lambda
এবং পছন্দ না করে কাজ করে Proc.new
। এর অর্থ রুবি ডকটি সঠিক নয়।
proc
মতো কাজ করে lambda
তবে Proc.new
1.9-র মতো কাজ করে acts পিটার ওয়াগনেটের উত্তর দেখুন।
lambda
একটি বেনামি পদ্ধতি। যেহেতু এটি একটি পদ্ধতি, তাই এটি একটি মান ফেরত দেয় এবং যে পদ্ধতিটি এটি বলে এটি এটিকে উপেক্ষা করা এবং ভিন্ন মান ফিরিয়ে দেওয়া সহ যা খুশি তা করতে পারে। এ Proc
কোড স্নিপেটে পেস্ট করার মতো। এটি কোনও পদ্ধতির মতো কাজ করে না। সুতরাং যখন কোনও রিটার্ন ঘটে তখন Proc
এটি সেই পদ্ধতির কোডটির অংশ যা এটি বলে।
আরও ব্যাখ্যা প্রদান করতে:
জয়ে বলেছেন যে রিটার্নের আচরণ Proc.new
অবাক করা। তবে আপনি যখন বিবেচনা করেন যে প্রোকনিউ একটি ব্লকের মতো আচরণ করে এটি অবাক হওয়ার মতো বিষয় নয় যে ঠিক ব্লকগুলি কীভাবে আচরণ করে। অন্যদিকে ল্যাম্বাস আরও পদ্ধতির মতো আচরণ করে।
এটি প্রকৃতপক্ষে ব্যাখ্যা করে যে লাম্বদা না থাকাকালীন যখন আরিটি (আর্গুমেন্টের সংখ্যা) আসে তখন প্রোকস কেন নমনীয়। ব্লকগুলিকে তাদের সমস্ত যুক্তি সরবরাহ করার প্রয়োজন হয় না তবে পদ্ধতিগুলি করে (যদি না কোনও ডিফল্ট সরবরাহ না করা হয়)। লাম্বদা আর্গুমেন্ট ডিফল্ট সরবরাহ করা রুবি ১.৮-এ কোনও বিকল্প নয়, এখন এটি রুবি ১.৯-এ বিকল্প ল্যাম্বদা সিনট্যাক্স (ওয়েবম্যাট দ্বারা উল্লিখিত) সহ সমর্থিত:
concat = ->(a, b=2){ "#{a}#{b}" }
concat.call(4,5) # => "45"
concat.call(1) # => "12"
এবং মিচিয়েল ডি মেরে (ওপি) প্রোকস এবং ল্যাম্বডা রুবি ১.৯-তে বিনয়ের সাথে একই আচরণ করছেন সম্পর্কে ভুল। আমি যাচাই করেছি যে তারা এখনও উপরে বর্ণিত 1.8 থেকে আচরণটি বজায় রাখে।
break
বিবৃতি প্রকৃতপক্ষে বা ল্যাম্বডাস উভয়ই বাস্তবে খুব একটা বোঝায় না। প্রকসগুলিতে, বিরতি আপনাকে প্রোক.নেউ থেকে ফিরিয়ে আনবে যা ইতিমধ্যে সম্পন্ন হয়েছে। ল্যাম্বডাটি ভেঙে ফেলার কোনও অর্থ হয় না যেহেতু এটি মূলত একটি পদ্ধতি এবং আপনি কোনও পদ্ধতির শীর্ষ স্তর থেকে কখনই ভাঙবেন না।
next
, redo
, এবং raise
উভয় Procs এবং lambdas একই আচরণ। যেখানে retry
উভয় ক্ষেত্রেই অনুমোদিত নয় এবং এটি ব্যতিক্রমও বাড়িয়ে তুলবে।
এবং অবশেষে, proc
পদ্ধতিটি কখনই ব্যবহার করা উচিত নয় কারণ এটি অসঙ্গত এবং অপ্রত্যাশিত আচরণ রয়েছে। রুবি ১.৮ এ এটি আসলে একটি লাম্বদা ফেরত দেয়! রুবি ১.৯ এ এটি স্থির করা হয়েছে এবং এটি একটি প্রকট প্রদান করে। আপনি যদি কোনও প্রোক তৈরি করতে চান তবে সাথে থাকুন Proc.new
।
আরও তথ্যের জন্য, আমি ও'রিলির দ্য রুবি প্রোগ্রামিং ল্যাঙ্গুয়েজকে অত্যন্ত পরামর্শ দিচ্ছি যা এই তথ্যের বেশিরভাগ জন্য আমার উত্স।
break
প্রোকস থেকে উত্থাপিত হয় LocalJumpError
, যেখানে ল্যাম্বডাস break
থেকে ঠিক return
( যেমন , return nil
) আচরণ করে ।
আমি এই পৃষ্ঠাটি পেয়েছি যা দেখায় যেগুলির মধ্যে পার্থক্য কী Proc.new
এবং lambda
। পৃষ্ঠা অনুসারে, কেবলমাত্র তফাতটি হল যে একটি ল্যাম্বডা যতটা আর্গুমেন্ট গ্রহণ করে সে সম্পর্কে কঠোর, যেখানে Proc.new
অনুপস্থিত যুক্তিগুলিকে রূপান্তর করে nil
। পার্থক্যটি চিত্রিত করে এখানে একটি উদাহরণ আইআরবি সেশন:
irb (প্রধান): 001: 0> l = ল্যাম্বদা {| x, y | x + y => # <প্রোক: 0x00007fc605ec0748 @ (আইআরবি): 1> irb (প্রধান): 002: 0> p = Proc.new {| x, y | x + y => # <প্রোক: 0x00007fc605ea8698 @ (আইআরবি): 2> irb (প্রধান): 003: 0> l.call "হ্যালো", "বিশ্ব" => "হেলিওরল্ড" irb (প্রধান): 004: 0> p.call "হ্যালো", "বিশ্ব" => "হেলিওরল্ড" irb (প্রধান): 005: 0> l.call "হ্যালো" যুক্তি ত্রুটি: আর্গুমেন্টের ভুল সংখ্যা (2 এর জন্য 1) থেকে (irb): 1 (irb) থেকে: 5: ইন 'কল' থেকে (irb): 5 থেকে: 0 irb (প্রধান): 006: 0> p.call "হ্যালো" TypeError: নীলকে স্ট্রিংয়ে রূপান্তর করতে পারে না (irb) থেকে: 2: `+ 'তে (irb) থেকে: 2 (irb) থেকে: 6: ইন 'কল' (irb) থেকে: 6 থেকে: 0
পৃষ্ঠাটি ল্যাম্বডা ব্যবহারের প্রস্তাব দেয় যদি আপনি বিশেষত ত্রুটি সহনশীল আচরণ না চান। আমি এই অনুভূতির সাথে একমত ল্যাম্বডা ব্যবহার করা বাচ্চাকে আরও সংক্ষিপ্ত বলে মনে হয় এবং এইরকম একটি তুচ্ছ পার্থক্যের সাথে, এটি গড় পরিস্থিতিতে আরও ভাল পছন্দ বলে মনে হয়।
রুবি ১.৯-এর জন্য, দুঃখিত, আমি এখনও ১.৯-এর দিকে নজর দিইনি, তবে আমি তারা কল্পনাও করি না যে তারা এগুলি এতটাই বদলে দেবে (যদিও এর জন্য আমার কথাটি গ্রহণ করবেন না, মনে হয় আপনি কিছু পরিবর্তন শুনেছেন, তাই) আমি সম্ভবত সেখানে ভুল)।
প্রোকটি বয়স্ক, তবে প্রত্যাবর্তনের শব্দার্থবিজ্ঞান আমার কাছে অত্যন্ত বিপরীত (কমপক্ষে আমি যখন ভাষা শিখছিলাম) কারণ:
ল্যাম্বদা কার্যকরীভাবে নিরাপদ এবং এর পক্ষে যুক্তিযুক্তভাবে সহজ - আমি সবসময় এটি প্রোকের পরিবর্তে ব্যবহার করি।
সূক্ষ্ম পার্থক্য সম্পর্কে আমি বেশি কিছু বলতে পারি না। তবে আমি উল্লেখ করতে পারি যে রুবি ১.৯ এখন ল্যাম্বডাস এবং ব্লকগুলির জন্য alচ্ছিক পরামিতিগুলিকে অনুমতি দেয় allows
1.9 এর নীচে ছুরিকাঘাতের ল্যাম্বডাসের জন্য নতুন সিনট্যাক্সটি এখানে রয়েছে:
stabby = ->(msg='inside the stabby lambda') { puts msg }
রুবি 1.8 এর সিনট্যাক্সটি ছিল না। উভয়ই ব্লক / ল্যাম্বডাস optionচ্ছিক আরোগুলিকে সমর্থন করার প্রচলিত পদ্ধতিটি করেনি:
# under 1.8
l = lambda { |msg = 'inside the stabby lambda'| puts msg }
SyntaxError: compile error
(irb):1: syntax error, unexpected '=', expecting tCOLON2 or '[' or '.'
l = lambda { |msg = 'inside the stabby lambda'| puts msg }
রুবি ১.৯, তবে পুরানো বাক্য গঠন দিয়েও optionচ্ছিক যুক্তি সমর্থন করে:
l = lambda { |msg = 'inside the regular lambda'| puts msg }
#=> #<Proc:0x0e5dbc@(irb):1 (lambda)>
l.call
#=> inside the regular lambda
l.call('jeez')
#=> jeez
আপনি যদি চিতাবাঘ বা লিনাক্সের জন্য রুবি 1.9 তৈরি করতে চান তবে এই নিবন্ধটি (নির্লজ্জ স্ব-প্রচার) দেখুন।
সংক্ষিপ্ত উত্তর: যা গুরুত্বপূর্ণ তা হল return
: ল্যাম্বদা নিজের থেকে ফিরে আসে এবং নিজের থেকে ফাংশন ফিরে আসে এবং এটি যে ফাংশন বলে called
কি কম পরিষ্কার তা হ'ল আপনি কেন প্রতিটি ব্যবহার করতে চান। লাম্বদা হ'ল আমরা প্রত্যাশা করি যা কার্যকরী প্রোগ্রামিং অর্থে জিনিসগুলি করা উচিত। এটি মূলত বর্তমান স্কোপটি স্বয়ংক্রিয়ভাবে আবদ্ধ হওয়ার সাথে একটি বেনামী পদ্ধতি। দুটির মধ্যে লাম্বদা হ'ল আপনার সম্ভবত ব্যবহার করা উচিত।
অন্যদিকে, প্রক নিজেই ভাষা প্রয়োগের জন্য সত্যই কার্যকর। উদাহরণস্বরূপ আপনি তাদের সাথে "যদি" বিবৃতি বা "for" লুপগুলি প্রয়োগ করতে পারেন। প্রোকের মধ্যে পাওয়া যে কোনও রিটার্ন সেই পদ্ধতিটি থেকে ফিরে আসবে যেটিকে এটি বলে, কেবল "যদি" বিবৃতিটি নয়। এটি ভাষাগুলি কীভাবে কাজ করে, "যদি" বিবৃতিগুলি কীভাবে কাজ করে, তাই আমার ধারণা রুবি প্রচ্ছদের অধীনে এটি ব্যবহার করে এবং তারা কেবল এটিকে প্রকাশ করেছিল কারণ এটি শক্তিশালী বলে মনে হয়েছিল।
আপনি যদি লুপ, যদি-অন্য নির্মাণগুলি ইত্যাদির মতো নতুন ভাষার নির্মাণ তৈরি করেন তবে আপনার কেবল এটির প্রয়োজন হবে You
কোয়েস্টনের তৃতীয় পদ্ধতির বিষয়ে আমি কোনও মন্তব্য লক্ষ্য করিনি, "প্রোক" যা অবমূল্যায়ন করা হয়েছে, তবে 1.8 এবং 1.9 এ ভিন্নভাবে পরিচালিত হয়েছে।
এখানে মোটামুটি ভার্বোজের উদাহরণ যা তিনটি অনুরূপ কলগুলির মধ্যে পার্থক্য দেখতে সহজ করে তোলে:
def meth1
puts "method start"
pr = lambda { return }
pr.call
puts "method end"
end
def meth2
puts "method start"
pr = Proc.new { return }
pr.call
puts "method end"
end
def meth3
puts "method start"
pr = proc { return }
pr.call
puts "method end"
end
puts "Using lambda"
meth1
puts "--------"
puts "using Proc.new"
meth2
puts "--------"
puts "using proc"
meth3
proc
1.8 এ একটি ল্যাম্বডা ফিরিয়ে দিয়েছিল; এটি এখন ১.৯-এ কোনও প্রকার ফেরত দেওয়ার জন্য স্থির করা হয়েছে - তবে এটি একটি ব্রেকিং পরিবর্তন; অতএব আর ব্যবহারের জন্য প্রস্তাবিত নয়
রুবিতে ক্লাবগুলি রুবীর সাথে কীভাবে ব্লক, ল্যাম্বডা এবং প্রুকের কাজ করে তার একটি ভাল ওভারভিউ।
ল্যাম্বদা অন্যান্য ভাষার মতো প্রত্যাশার মতো কাজ করে।
তারযুক্ত Proc.new
অবাক এবং বিভ্রান্তিকর।
return
উত্পাদিত বিবৃতিটি কেবল Proc.new
নিজের থেকে নয়, এটি ঘেরানো পদ্ধতি থেকেও নিয়ন্ত্রণ ফিরিয়ে আনবে ।
def some_method
myproc = Proc.new {return "End."}
myproc.call
# Any code below will not get executed!
# ...
end
আপনি যুক্তি দিতে পারেন যে Proc.new
ব্লকের মতো কোডটি এনকোলেসিং পদ্ধতিতে সন্নিবেশ করানো হয়। কিন্তু Proc.new
একটি বস্তু তৈরি করে, যখন ব্লক একটি বস্তুর অংশ ।
এবং ল্যাম্বদা এবং এর মধ্যে অন্য পার্থক্য রয়েছে Proc.new
, যা তাদের (ভুল) তর্কগুলি পরিচালনা করা। ল্যাম্বদা এটি সম্পর্কে অভিযোগ করে, যখন Proc.new
অতিরিক্ত যুক্তি উপেক্ষা করে বা যুক্তিগুলির অনুপস্থিতিকে শূন্য বলে মনে করে।
irb(main):021:0> l = -> (x) { x.to_s }
=> #<Proc:0x8b63750@(irb):21 (lambda)>
irb(main):022:0> p = Proc.new { |x| x.to_s}
=> #<Proc:0x8b59494@(irb):22>
irb(main):025:0> l.call
ArgumentError: wrong number of arguments (0 for 1)
from (irb):21:in `block in irb_binding'
from (irb):25:in `call'
from (irb):25
from /usr/bin/irb:11:in `<main>'
irb(main):026:0> p.call
=> ""
irb(main):049:0> l.call 1, 2
ArgumentError: wrong number of arguments (2 for 1)
from (irb):47:in `block in irb_binding'
from (irb):49:in `call'
from (irb):49
from /usr/bin/irb:11:in `<main>'
irb(main):050:0> p.call 1, 2
=> "1"
বিবিডাব্লু, proc
রুবি ১.৮ এ ল্যাম্বডা তৈরি করে, অন্যদিকে রুবি ১.৯++ এমন আচরণ করে Proc.new
যা সত্যই বিভ্রান্তিকর।
অ্যাকর্ডিয়ান গায়ের প্রতিক্রিয়াটি বিস্তারিতভাবে জানাতে:
লক্ষ্য করুন যে Proc.new
একটি ব্লক পাস করে একটি প্রক্ট আউট তৈরি করে। আমি বিশ্বাস করি যে lambda {...}
এটি একটি ব্লককে অতিক্রম করে এমন একটি মেথড কলের চেয়ে শাব্দিকের ধরণের হিসাবে পার্স করা হয়েছে। return
কোনও মেথড কলের সাথে সংযুক্ত ব্লকের ভিতরে থেকে ইনিং পদ্ধতিতে ফিরে আসবে, ব্লক নয়, এবংProc.new
একটি উদাহরণ।
(এটি 1.8 I আমি জানি না এটি কীভাবে 1.9 এ অনুবাদ করে)
আমি এই বিষয়ে কিছুটা দেরি করেছি, তবে Proc.new
মন্তব্যে মোটেই উল্লেখ করা হয়নি এমন একটি দুর্দান্ত তবে সামান্য জানা জিনিস রয়েছে । যেমন ডকুমেন্টেশন দ্বারা :
Proc::new
কেবল একটি সংযুক্ত ব্লকযুক্ত কোনও পদ্ধতির মধ্যে কোনও ব্লক ছাড়াই ডাকা যেতে পারে, সেই ক্ষেত্রে সেই ব্লকটিProc
বস্তুতে রূপান্তরিত হয় ।
এটি বলেছিল, Proc.new
ফলন পদ্ধতিতে চেইন করতে দেয়:
def m1
yield 'Finally!' if block_given?
end
def m2
m1 &Proc.new
end
m2 { |e| puts e }
#⇒ Finally!
&block
আর্গুমেন্ট ঘোষণার মতো একই কাজ def
করে তবে ডিএফ আরগ তালিকায় এটি না করেই।
এটি জোর দেওয়া উচিত যে return
কোনও প্রক্সে লেক্সিক্যালি এনকোলেসিং পদ্ধতি থেকে অর্থাত্ প্র্যাকটি তৈরি করা হয়েছিল , যেখানে পদ্ধতিটি প্রোকটি তৈরি করা হয়েছিল , সে পদ্ধতিটি নয় যা প্রোক নামে পরিচিত। এটি প্রকসগুলির বন্ধ সম্পত্তি হ'ল একটি পরিণতি। সুতরাং নিম্নলিখিত কোড কিছুই আউটপুট:
def foo
proc = Proc.new{return}
foobar(proc)
puts 'foo'
end
def foobar(proc)
proc.call
puts 'foobar'
end
foo
যদিও প্রকল্পটি কার্যকর করে foobar
, এটি তৈরি করা হয়েছিল foo
এবং তাই return
প্রস্থান করা হয় foo
, কেবল তা নয় foobar
। চার্লস ক্যালওয়েল যেমন উপরে লিখেছেন, এটিতে এটির একটি খুব অনুভূতি রয়েছে। আমার মতে, return
একটি ব্লকে এটি ঠিক আছে যা এর লেজিকাল প্রসঙ্গে কার্যকর করা হয়, তবে যখন কোনও প্রসঙ্গে ব্যবহার করা হয় যা ভিন্ন প্রসঙ্গে প্রয়োগ করা হয় তখন এটি অনেক কম স্বজ্ঞাত হয়।
আচরণের মধ্যে পার্থক্য return
হ'ল আইএমএইচও 2 এর মধ্যে সবচেয়ে গুরুত্বপূর্ণ পার্থক্য I
proc {}
। কখন এটি কার্যকর হয়েছে আমি নিশ্চিত নই, তবে প্রোক.নেউ টাইপ করার চেয়ে এটি (সামান্য) সহজ।