Lambda का उपयोग कब करें, Proc.new का उपयोग कब करें?

रूबी 1.8 में, एक तरफ proc / lambda के बीच सूक्ष्म मतभेद हैं, और दूसरे पर Proc.new हैं।

  • वे मतभेद क्या हैं?
  • क्या आप निर्णय ले सकते हैं कि किसको चुनना है?
  • रुबी 1.9 में, proc और lambda अलग हैं। सौदा क्या है?
0
जोड़ा संपादित
विचारों: 1
आपने जवाब स्वीकार कर लिया है जो केवल कहता है कि proc और lambda के बीच क्या अंतर है, जबकि आपके प्रश्न का शीर्षक उन चीजों का उपयोग कब करना है
जोड़ा लेखक Shri, स्रोत
यह भी देखें: मैटज़ और फ्लानगन द्वारा रूबी प्रोग्रामिंग भाषा पुस्तक, इसने व्यापक रूप से इस विषय को कवर किया है। proc एक ब्लॉक - उपज semantics की तरह व्यवहार करता है, जहां लैम्ब्डा एक विधि की तरह व्यवहार करता है - विधि कॉल semantics। इसके अलावा, ब्रेक, एट। सभी procs n lambdas में diffave व्यवहार करते हैं
जोड़ा लेखक Gishu, स्रोत
कई कारणों से प्रकाशन साइट में CEWP का उपयोग करने की अनुशंसा नहीं की जाती है जैसे कि यह यूआरएल को पूर्ण यूआरएल के रूप में स्टोर करता है, संस्करण इतिहास नहीं है, आदि इसके बारे में andrewconnell.com/blog/archive/2009/02/01/& hellip;
जोड़ा लेखक Greg, स्रोत
पहले यह नहीं सुना था, लेकिन यह समझ में आता है। यह प्रयास उन लोगों में से एक था जहां हमने कम कटौती करने की कोशिश की। इस पोस्ट के कुछ ही समय बाद हमने उस पथ को तोड़ दिया और दृश्य पृष्ठों का उपयोग करने के बजाय श्रेणियों के लिए विशिष्ट लेआउट विकसित करने का निर्णय लिया।
जोड़ा लेखक Daemin, स्रोत

13 उत्तर

एसपी डिजाइनर का उपयोग करके इसे जांचने का प्रयास करें।

2
जोड़ा
ठीक है कि काम किया। यह बहुत अजीब बात है क्योंकि हमें बदलावों के 10 सेटों के लिए पहले इसे जांचना नहीं था। चूंकि विचारों में सामग्री अनुमोदन नहीं है, और यह इंटरफ़ेस के माध्यम से नहीं किया जा सकता है, यह एसपीडी में ऐसा करने के लिए मेरे साथ नहीं हुआ था। धन्यवाद!
जोड़ा लेखक Daemin, स्रोत

मैंने यह पृष्ठ पाया जो दिखाता है कि Proc.new और < कोड> लैम्ब्डा हैं। पृष्ठ के मुताबिक, केवल अंतर यह है कि लैम्ब्डा इसे स्वीकार किए गए तर्कों की संख्या के बारे में सख्त है, जबकि Proc.new गायब तर्कों को nil में परिवर्तित करता है। अंतर का वर्णन करने वाला आईआरबी सत्र यहां एक उदाहरण दिया गया है:

irb(main):001:0> l = lambda { |x, y| x + y }
=> #
irb(main):002:0> p = Proc.new { |x, y| x + y }
=> #
irb(main):003:0> l.call "hello", "world"
=> "helloworld"
irb(main):004:0> p.call "hello", "world"
=> "helloworld"
irb(main):005:0> l.call "hello"
ArgumentError: wrong number of arguments (1 for 2)
    from (irb):1
    from (irb):5:in `call'
    from (irb):5
    from :0
irb(main):006:0> p.call "hello"
TypeError: can't convert nil into String
    from (irb):2:in `+'
    from (irb):2
    from (irb):6:in `call'
    from (irb):6
    from :0

The page also recommends using lambda unless you specifically want the error tolerant behavior. I agree with this sentiment. Using a lambda seems a tad more concise, and with such an insignificant difference, it seems the better choice in the average situation.

As for ruby 1.9, sorry, I haven't looked into 1.9 yet, but I don't imagine they would change it all that much (don't take my word for it though, it seems you have heard of some changes, so I am probably wrong there).

0
जोड़ा
procs lambdas से अलग भी लौटते हैं।
जोड़ा लेखक Cam, स्रोत
"" "Proc.new गुम तर्कों को शून्य में परिवर्तित करता है" "Proc.new अतिरिक्त तर्कों को भी अनदेखा करता है (बेशक लैम्ब्डा इसे एक त्रुटि के साथ शिकायत करता है)।
जोड़ा लेखक weakish, स्रोत

return के साथ व्यवहार में अंतर आईएमएचओ 2 के बीच सबसे महत्वपूर्ण अंतर है। मैं लैम्ब्डा भी पसंद करता हूं क्योंकि यह Proc.new से कम टाइपिंग है :-)

0
जोड़ा
अपडेट करने के लिए: procs अब proc {} का उपयोग करके बनाया जा सकता है। मुझे यकीन नहीं है कि यह प्रभावी होने पर, लेकिन Proc.new टाइप करने से यह थोड़ा (थोड़ा) आसान है।
जोड़ा लेखक aceofbassgreg, स्रोत

Accordion गाय की प्रतिक्रिया पर विस्तार करने के लिए:

ध्यान दें कि Proc.new एक ब्लॉक पारित करके एक proc out बनाता है। मेरा मानना ​​है कि lambda {...} को एक ब्लॉक कॉल करने के बजाय एक विधि कॉल के बजाय शाब्दिक प्रकार के रूप में पार्स किया गया है। एक विधि कॉल से जुड़े ब्लॉक के अंदर वापसी आईएनजी विधि से वापस आ जाएगा, ब्लॉक नहीं, और Proc.new केस इस पर एक उदाहरण है।

(यह 1.8 है। मुझे नहीं पता कि यह कैसे 1.9 का अनुवाद करता है।)

0
जोड़ा

मुझे इस पर थोड़ा देर हो चुकी है, लेकिन टिप्पणियों में उल्लिखित 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!
0
जोड़ा
दिलचस्प है, यह def में def block तर्क घोषित करने जैसा ही है, लेकिन def arg सूची में ऐसा करने के बिना।
जोड़ा लेखक jrochkind, स्रोत

इसे देखने का एक अच्छा तरीका यह है कि लैम्ब्डा को अपने दायरे में निष्पादित किया जाता है (जैसे कि यह एक विधि कॉल था), जबकि प्रोसेस को कॉलिंग विधि के साथ निष्पादित इनलाइन के रूप में देखा जा सकता है, कम से कम यह तय करने का एक अच्छा तरीका है कि किस का उपयोग करना है प्रत्येक मामले में।

0
जोड़ा

मैं सूक्ष्म मतभेदों के बारे में ज्यादा नहीं कह सकता। हालांकि, मैं इंगित कर सकता हूं कि रूबी 1.9 अब लैम्बडा और ब्लॉक के लिए वैकल्पिक पैरामीटर की अनुमति देता है।

1.9 के तहत स्टैबी लैम्बडास के लिए नया वाक्यविन्यास यहां दिया गया है:

stabby = ->(msg='inside the stabby lambda') { puts msg }

रूबी 1.8 में उस वाक्यविन्यास नहीं था। ब्लॉकों / लैम्बडास घोषित करने का पारंपरिक तरीका वैकल्पिक तर्कों का समर्थन नहीं करता है:

# 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 }

रूबी 1.9, हालांकि, पुराने वाक्यविन्यास के साथ भी वैकल्पिक तर्कों का समर्थन करता है:

l = lambda { |msg = 'inside the regular lambda'|  puts msg }
#=> #
l.call
#=> inside the regular lambda
l.call('jeez')
#=> jeez

If you wanna build Ruby1.9 for Leopard or Linux, check out this article (shameless self promotion).

0
जोड़ा
आप ब्लॉकों में केवल डिफ़ॉल्ट पैरामीटर प्रदर्शित नहीं कर रहे हैं, केवल lambdas
जोड़ा लेखक iconoclast, स्रोत
लैम्ब्डा के भीतर वैकल्पिक पैरा बहुत जरूरी थे, मुझे खुशी है कि उन्होंने इसे 1.9 में जोड़ा है। मुझे लगता है कि ब्लॉक भी वैकल्पिक पैरामीटर भी हो सकता है (1.9 में)?
जोड़ा लेखक mpd, स्रोत

आगे स्पष्टीकरण प्रदान करने के लिए:

जॉय का कहना है कि Proc.new का वापसी व्यवहार आश्चर्यजनक है। हालांकि जब आप मानते हैं कि Proc.new एक ब्लॉक की तरह व्यवहार करता है तो यह आश्चर्य की बात नहीं है क्योंकि यह बिल्कुल सही है कि ब्लॉक कैसे व्यवहार करते हैं। दूसरी ओर भेड़िये विधियों की तरह व्यवहार करते हैं।

यह वास्तव में बताता है कि जब धन की बात आती है (तर्कों की संख्या) की प्रक्रियाएं लचीली नहीं होती हैं, जबकि प्रक्रियाएं लचीली होती हैं। ब्लॉक को उनके सभी तर्कों की आवश्यकता नहीं होती है लेकिन विधियां होती हैं (जब तक कोई डिफ़ॉल्ट प्रदान नहीं किया जाता है)। जबकि लैम्ब्डा तर्क डिफ़ॉल्ट प्रदान करना रूबी 1.8 में कोई विकल्प नहीं है, अब यह वैकल्पिक लैम्ब्डा वाक्यविन्यास (जैसा कि वेबमैट द्वारा नोट किया गया है) के साथ रुबी 1.9 में समर्थित है:

concat = ->(a, b=2){ "#{a}#{b}" }
concat.call(4,5) # => "45"
concat.call(1)   # => "12"

और मिचिल डी मारे (ओपी) प्रो और लैम्बडा रूबी 1.9 में धर्मार्थता के साथ व्यवहार करने के बारे में गलत है। मैंने सत्यापित किया है कि वे अभी भी ऊपर निर्दिष्ट अनुसार 1.8 से व्यवहार बनाए रखते हैं।

break statements don't actually make much sense in either Procs or lambdas. In Procs, the break would return you from Proc.new which has already been completed. And it doesn't make any sense to break from a lambda since it's essentially a method, and you would never break from the top level of a method.

next, redo, and raise behave the same in both Procs and lambdas. Whereas retry is not allowed in either and will raise an exception.

और अंत में, proc विधि का उपयोग कभी भी नहीं किया जाना चाहिए क्योंकि यह असंगत है और अप्रत्याशित व्यवहार है। रूबी 1.8 में यह वास्तव में एक भेड़ का बच्चा देता है! रूबी 1.9 में यह तय किया गया है और यह एक प्रक्रिया देता है। यदि आप एक प्रक्रिया बनाना चाहते हैं, तो Proc.new के साथ चिपके रहें।

अधिक जानकारी के लिए, मैं ओ'रेली की रूबी प्रोग्रामिंग भाषा की अत्यधिक अनुशंसा करता हूं जो कि अधिकांश जानकारी के लिए मेरा स्रोत है।

0
जोड़ा
"" "हालांकि जब आप मानते हैं कि Proc.new एक ब्लॉक की तरह व्यवहार करता है तो यह आश्चर्य की बात नहीं है क्योंकि यह बिल्कुल सही है कि ब्लॉक कैसे व्यवहार करते हैं।" "<- ब्लॉक किसी ऑब्जेक्ट का हिस्सा है, जबकि Proc.new ऑब्जेक्ट बनाता है। लैम्ब्डा और Proc.new दोनों एक वस्तु बनाता है जिसका वर्ग प्रो है, क्यों diff?
जोड़ा लेखक weakish, स्रोत

lambda और Proc.new के साथ बनाई गई procs के साथ बनाई गई प्रोसेस के बीच एक और महत्वपूर्ण लेकिन सूक्ष्म अंतर यह है कि वे return कथन को कैसे प्रबंधित करते हैं:

  • In a lambda-created proc, the return statement returns only from the proc itself
  • In a Proc.new-created proc, the return statement is a little more surprising: it returns control not just from the proc, but also from the method enclosing the proc!

कार्रवाई में lambda -created proc's 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 -created proc's 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"

इस आश्चर्यजनक व्यवहार (साथ ही साथ कम टाइपिंग) के लिए धन्यवाद, मैं procs बनाते समय lambda Proc.new से अधिक का उपयोग करने का पक्ष लेता हूं।

0
जोड़ा
जोड़ा लेखक ma11hew28, स्रोत
मेरा मानना ​​है कि एक बड़ा अंतर यह भी है कि Proc एस त्रुटियों को फेंक नहीं देते हैं जब आप अनुपलब्ध / अतिरिक्त तर्क प्रदान करते हैं, जबकि lambda s एक तर्कों की गलत संख्या फेंक देगा </ कोड> त्रुटि
जोड़ा लेखक Edmund, स्रोत
@mattdipasquale मेरे परीक्षणों में, proc lambda जैसे कार्य करता है और वापसी विवरणों के संबंध में Proc.new जैसा नहीं है। इसका मतलब है कि रूबी डॉक्टर गलत है।
जोड़ा लेखक Kelvin, स्रोत
@mattdipasquale क्षमा करें मैं केवल आधा सही था। proc lambda जैसे 1.8 में कार्य करता है, लेकिन 1.9> Proc.new जैसे 1.9 में कार्य करता है। पीटर वैगनेट का जवाब देखें।
जोड़ा लेखक Kelvin, स्रोत
फिर proc विधि भी है। क्या यह सिर्फ Proc.new के लिए एक शॉर्टेंड है?
जोड़ा लेखक panzi, स्रोत
यह "आश्चर्यजनक" व्यवहार क्यों है? एक lambda एक अज्ञात विधि है। चूंकि यह एक विधि है, यह एक मूल्य देता है, और जिस विधि को इसे बुलाया जाता है, वह इसे अनदेखा करके और एक अलग मूल्य लौटने सहित जो कुछ भी चाहता है उसके साथ कर सकता है। एक Proc कोड स्निपेट में पेस्ट करने जैसा है। यह एक विधि की तरह कार्य नहीं करता है। तो जब Proc के भीतर कोई वापसी होती है, तो वह उस विधि के कोड का हिस्सा है जिसे इसे कहा जाता है।
जोड़ा लेखक Arcolye, स्रोत
जैसा कि आर्कोले द्वारा इंगित किया गया है, "रूबी में प्रोसेस कोड स्निपेट में ड्रॉप हैं, तरीकों से नहीं"। robertsosinski.com/2008/12/ से 21 / & hellip; । तो ऐसा लगता है कि वापसी whowouldwin2 में ही है।
जोड़ा लेखक Pietro, स्रोत

मैंने खोजन में तीसरी विधि पर कोई टिप्पणी नहीं देखी, "proc" जिसे बहिष्कृत किया गया है, लेकिन 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
0
जोड़ा
मुझे लगता है कि पिकैक्स कहीं एक फुटनोट में कहता है कि proc प्रभावी रूप से वंचित या कुछ है। मेरे पास सटीक पृष्ठ संख्या नहीं है।
जोड़ा लेखक dertoni, स्रोत
@banister: proc ने 1.8 में एक लैम्ब्डा लौटाया; अब इसे 1.9 में एक प्रोसेस वापस करने के लिए तय किया गया है - हालांकि यह एक तोड़ने वाला बदलाव है; इसलिए अब और उपयोग करने की अनुशंसा नहीं की जाती है
जोड़ा लेखक Gishu, स्रोत
आपने कहां पढ़ा था कि proc को बहिष्कृत किया गया था?
जोड़ा लेखक horseyguy, स्रोत
मैट्ज़ ने कहा था कि उन्होंने इसे हटाने की योजना बनाई क्योंकि यह proc और Proc.new अलग-अलग परिणामों को वापस करने में भ्रमित था। 1.9 में वे वही व्यवहार करते हैं (proc Proc.new के लिए उपनाम है)। eigenclass.org/hiki/Changes+in+Ruby+1.9#l47
जोड़ा लेखक Dave Rapin, स्रोत

संक्षिप्त उत्तर: क्या मायने रखता है return करता है: लैम्ब्डा स्वयं से बाहर निकलता है, और प्रो स्वयं से बाहर निकलता है और वह फ़ंक्शन जिसे इसे कहा जाता है।

कम स्पष्ट क्या है कि आप प्रत्येक का उपयोग क्यों करना चाहते हैं। लैम्ब्डा वह है जो हम उम्मीद करते हैं कि चीजों को एक कार्यात्मक प्रोग्रामिंग भावना में करना चाहिए। यह मूल रूप से वर्तमान गुंजाइश के साथ एक अज्ञात विधि है। दो में से, लैम्ब्डा वह है जिसे आप शायद इस्तेमाल कर रहे हैं।

दूसरी ओर, प्रक्रिया भाषा को लागू करने के लिए वास्तव में उपयोगी है। उदाहरण के लिए आप उनके साथ "if" कथन या "के लिए" लूप लागू कर सकते हैं। Proc में मिली कोई भी वापसी उस विधि से वापस आ जाएगी जो इसे "अगर" कथन नहीं देती है। इस प्रकार भाषाएं काम करती हैं, कैसे "अगर" कथन काम करते हैं, तो मेरा अनुमान है कि रूबी कवर के तहत इसका उपयोग करता है और उन्होंने इसे अभी खुलासा किया क्योंकि यह शक्तिशाली लग रहा था।

यदि आपको नई भाषा संरचनाएं जैसे लूप, अगर-अन्य संरचनाएं इत्यादि बना रही हैं, तो आपको केवल इसकी आवश्यकता होगी।

0
जोड़ा

Understanding ruby Blocks, Procs and Lambdas by Robert Sosinski clearly explains these programming concepts and reinforces the explanations with example code. Method objects are related and covered as well.

0
जोड़ा

लैम्बडा अन्य भाषाओं की तरह अपेक्षित काम करता है।

वायर्ड Proc.new आश्चर्यजनक और भ्रमित है।

Proc.new द्वारा बनाई गई proc में return कथन न केवल अपने आप से नियंत्रण वापस करेगा, बल्कि इसे संलग्न करने वाली विधि से भी

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 }
=> #
irb(main):022:0> p = Proc.new { |x| x.to_s}
=> #
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 `
' 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 `
' irb(main):050:0> p.call 1, 2 => "1"

BTW, proc in ruby 1.8 creates a lambda, while in ruby 1.9+ behaves like Proc.new, which is really confusing.

0
जोड़ा