রুবি ১.৮-তে, একদিকে প্র্যাক / ল্যাম্বডার মধ্যে এবং অন্যদিকে সূক্ষ্ম পার্থক্য রয়েছে 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.new1.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
proc1.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 {}। কখন এটি কার্যকর হয়েছে আমি নিশ্চিত নই, তবে প্রোক.নেউ টাইপ করার চেয়ে এটি (সামান্য) সহজ।