2009-05-01 11 views
115

अगर मैं इस तरह की एक रूबी कार्यों को परिभाषित:रूबी वैकल्पिक पैरामीटर

def ldap_get (base_dn, filter, scope=LDAP::LDAP_SCOPE_SUBTREE, attrs=nil) 

मैं इसे केवल पहले 2 और पिछले आर्ग की आपूर्ति कैसे फोन कर सकते हैं?

ldap_get(base_dn, filter, , X) 

संभव है या यदि यह संभव है, तो यह कैसे किया जा सकता है?

उत्तर

122

वर्तमान में रूबी के साथ यह संभव नहीं है। आप तरीकों से 'खाली' विशेषताओं को पारित नहीं कर सकते हैं।

ldap_get(base_dn, filter, nil, X) 

बहरहाल, यह नहीं के बराबर है, न कि LDAP :: LDAP_SCOPE_SUBTREE के दायरे सेट हो जाएगा: निकटतम आप प्राप्त कर सकते हैं पारित करने के लिए नहीं के बराबर है।

आप क्या कर सकते अपनी पद्धति के भीतर डिफ़ॉल्ट मान सेट है:

def ldap_get(base_dn, filter, scope = nil, attrs = nil) 
    scope ||= LDAP::LDAP_SCOPE_SUBTREE 
    ... do something ... 
end 

अब अगर आप विधि के रूप में ऊपर कहते हैं, व्यवहार के रूप में आप उम्मीद होगी।

+21

इस विधि के साथ थोड़ा गचाचा: उदा। यदि आप 'स्कोप' के लिए डिफ़ॉल्ट मान बनाने की कोशिश कर रहे हैं और आप 'झूठी' में गुजरते हैं, तो 'स्कोप || = true' काम नहीं करेगा। यह 'nil' के समान मूल्यांकन करता है और इसे 'सत्य' –

+4

पर सेट करेगा, क्या यह उत्तर के 3 साल बाद रूबी के वर्तमान संस्करण के साथ संभव है? – dalloliogm

+1

@ जोशपिनटर, अच्छा स्पष्टीकरण। मूल रूप से || = एक = बी या सी नहीं है, मैं 'xyz || = true' देखकर cringed। यह कह रहा है कि यह शून्य है, यह हमेशा सच है। यदि यह सच है, तो यह सच है। –

3

ldap_get को परिभाषित करने के तरीके से ऐसा करना संभव नहीं है। हालांकि, अगर आप ldap_get इस तरह परिभाषित करते हैं:

def ldap_get (base_dn, filter, attrs=nil, scope=LDAP::LDAP_SCOPE_SUBTREE) 
अब

आप कर सकते हैं:

ldap_get(base_dn, filter, X) 

लेकिन अब आप समस्या यह है कि आप इसे पहले दो आर्ग और पिछले आर्ग के साथ फोन नहीं कर सकते हैं (है पहले की तरह ही समस्या है लेकिन अब अंतिम तर्क अलग है)।

इसके लिए तर्क सरल है: रूबी में प्रत्येक तर्क को डिफ़ॉल्ट मान रखने की आवश्यकता नहीं है, इसलिए आप इसे निर्दिष्ट तरीके से कॉल नहीं कर सकते हैं। आपके मामले में, उदाहरण के लिए, पहले दो तर्कों में डिफ़ॉल्ट मान नहीं हैं।

134

आप विकल्प हैश का उपयोग करके लगभग हमेशा बेहतर होते हैं।

def ldap_get(base_dn, filter, options = {}) 
    options[:scope] ||= LDAP::LDAP_SCOPE_SUBTREE 
    ... 
end 

ldap_get(base_dn, filter, :attrs => X) 
+23

एक आम रणनीति एक डिफ़ॉल्ट विकल्प हैश के लिए और जो कुछ में विलय में पारित किया गया था है: 'विकल्प = default_options.merge (विकल्प)' –

+4

मैं इस प्रोत्साहित नहीं करते क्योंकि विकल्प बताते हैं कि क्या विधि की उम्मीद है या क्या डिफ़ॉल्ट मान –

0

यह संभव है :) बस परिभाषा

def ldap_get (base_dn, filter, scope=LDAP::LDAP_SCOPE_SUBTREE, attrs=nil) 

बदलने के लिए

def ldap_get (base_dn, filter, *param_array, attrs=nil) 
scope = param_array.first || LDAP::LDAP_SCOPE_SUBTREE 

गुंजाइश अपनी पहली जगह पर सरणी में अब हो जाएगा। जब आप 3 तर्क देते हैं, तो आप सौंपा गया होगा base_dn, फिल्टर और attrs और param_array हो जाएगा [] जब 4 और अधिक तर्क तो param_array हो जाएगा [argument1, or_more, and_more]

नकारात्मक पहलू यह है ... यह अस्पष्ट समाधान है, वास्तव में बदसूरत। यह जवाब देना है कि रूबी में फ़ंक्शन कॉल के बीच में तर्क छोड़ना संभव है :)

आपको एक और चीज है जो आपको दायरे के डिफ़ॉल्ट मान को फिर से लिखना है।

+3

हैं यह समाधान पूरी तरह से गलत है। यह एक splat ('* param_array') के बाद डिफ़ॉल्ट मान पैरामीटर (' attrs = nil') का उपयोग करने के लिए एक वाक्यविन्यास त्रुटि है। –

+3

-1: एरिक सही है। Irb 2.0.0p247 में एक वाक्यविन्यास त्रुटि का कारण बनता है। _ रूबी प्रोग्रामिंग भाषा_ के मुताबिक रूबी 1.8 में स्प्लिट पैरामीटर को 'और पैरामीटर' को छोड़कर अंतिम होना था, लेकिन रूबी 1.9 में इसके बाद "सामान्य पैरामीटर" भी हो सकते थे। किसी भी मामले में एक splat के साथ पैरामीटर के बाद एक डिफ़ॉल्ट कानूनी के साथ एक पैरामीटर था। – andyg0808

+0

रूबी प्रोग्रामिंग भाषा पृष्ठ 186/187 स्प्लट विधियों के साथ उपयोग करने के लिए ठीक है। जब तक इसका उपयोग नहीं किया जाता है तब तक विधि में यह अंतिम पैरामीटर होना चाहिए। – rupweb

0

हाल ही में मुझे इस के आसपास एक रास्ता मिला। मैं सरणी में तत्वों को रखने या त्यागने के लिए, वैकल्पिक पैरामीटर के साथ सरणी वर्ग में एक विधि बनाना चाहता था।

जिस तरह से मैंने इसे अनुकरण किया था, पैरामीटर के रूप में एक सरणी पास करके, और तब जांच कर रहा था कि उस सूचकांक का मान शून्य था या नहीं।

class Array 
    def ascii_to_text(params) 
    param_len = params.length 
    if param_len > 3 or param_len < 2 then raise "Invalid number of arguments #{param_len} for 2 || 3." end 
    bottom = params[0] 
    top  = params[1] 
    keep = params[2] 
    if keep.nil? == false 
     if keep == 1 
     self.map{|x| if x >= bottom and x <= top then x = x.chr else x = x.to_s end} 
     else 
     raise "Invalid option #{keep} at argument position 3 in #{p params}, must be 1 or nil" 
     end 
    else 
     self.map{|x| if x >= bottom and x <= top then x = x.chr end}.compact 
    end 
    end 
end 

विभिन्न मापदंडों के साथ हमारी कक्षा विधि बाहर की कोशिश कर रहा:

array = [1, 2, 97, 98, 99] 
p array.ascii_to_text([32, 126, 1]) # Convert all ASCII values of 32-126 to their chr value otherwise keep it the same (That's what the optional 1 is for) 

उत्पादन: ["1", "2", "a", "b", "c"]

ठीक है, शांत योजना के अनुसार काम करता है। आइए जांच लें और देखें कि क्या होता है यदि हम सरणी में तीसरे पैरामीटर विकल्प (1) में पास नहीं करते हैं।

array = [1, 2, 97, 98, 99] 
p array.ascii_to_text([32, 126]) # Convert all ASCII values of 32-126 to their chr value else remove it (1 isn't a parameter option) 

उत्पादन: ["a", "b", "c"]

आप देख सकते हैं, सरणी में तीसरा विकल्प हटा दिया गया है, इस प्रकार विधि में एक अलग अनुभाग को शुरू करने तथा सभी ASCII मूल्यों है कि हमारे रेंज में नहीं हैं को हटाने (32 -126)

वैकल्पिक रूप से, हम पैरामीटर में शून्य के रूप में मूल्य जारी कर सकते थे। कौन सा निम्नलिखित कोड ब्लॉक के लिए इसी तरह दिखेगा:

def ascii_to_text(top, bottom, keep = nil) 
    if keep.nil? 
    self.map{|x| if x >= bottom and x <= top then x = x.chr end}.compact 
    else 
    self.map{|x| if x >= bottom and x <= top then x = x.chr else x = x.to_s end} 
end 
1

1) आप विधि (Why doesn't ruby support method overloading?) ओवरलोड नहीं कर सकते हैं तो क्यों एक नई पद्धति पूरी तरह लिख नहीं?

2) मैंने शून्य या अधिक लंबाई की सरणी के लिए स्प्लट ऑपरेटर * का उपयोग कर एक समान समस्या हल की। फिर, अगर मैं पैरामीटर (ओं) को पास करना चाहता हूं, तो इसे सरणी के रूप में व्याख्या किया जाता है, लेकिन अगर मैं बिना किसी पैरामीटर के विधि को कॉल करना चाहता हूं तो मुझे कुछ भी पास नहीं करना पड़ेगा। देखें रूबी प्रोग्रामिंग भाषा पृष्ठों 186/187

44

समय पर और के बाद से संस्करण 2 रूबी नामित करने का समर्थन करता मापदंडों ले जाया गया है:,

def ldap_get (base_dn, filter, scope: "some_scope", attrs: nil) 
    p attrs 
end 

ldap_get("first_arg", "second_arg", attrs: "attr1, attr2") # => "attr1, attr2" 
+0

तुम भी अतिरिक्त अपरिभाषित कीवर्ड तर्क इकट्ठा करने के लिए एक डबल सूचक का उपयोग कर सकते हैं। यह इस मुद्दे से संबंधित है: http://stackoverflow.com/a/35259850/160363 –

0

आप आंशिक आवेदन के साथ ऐसा कर सकता है, हालांकि नामित चरों का उपयोग कर निश्चित रूप से अधिक करने के लिए सुराग पठनीय कोड। http://ejohn.org/blog/partial-functions-in-javascript/

Function.prototype.partial = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments); 
    return function(){ 
    var arg = 0; 
    for (var i = 0; i < args.length && arg < arguments.length; i++) 
     if (args[i] === undefined) 
     args[i] = arguments[arg++]; 
    return fn.apply(this, args); 
    }; 
}; 

यह शायद (मूलरूप विरासत को छोड़ कर) रूबी में ही सिद्धांत लागू करने के लिए संभव हो जाएगा: जॉन Resig 2008 में एक ब्लॉग लेख कैसे जावास्क्रिप्ट में यह करने के लिए के बारे में लिखा था।

संबंधित मुद्दे