रूबी वैकल्पिक मापदंडों


121

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

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

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

ldap_get( base_dn, filter, , X)

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

जवाबों:


131

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

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
इस विधि के साथ थोड़ा गौचा: जैसे यदि आप scopeसत्य के लिए डिफ़ॉल्ट मान बनाने की कोशिश कर रहे हैं और आप इसमें से गुजरते हैं false, scope ||= trueतो काम नहीं करेगा। यह उसी तरह का मूल्यांकन करता है nilऔर इसे करने के लिए सेट करेगाtrue
यहोशू पिंटर

4
क्या यह उत्तर के वर्तमान संस्करण के साथ संभव है, इस उत्तर के 3 साल बाद?
dalloliogm

1
@JoshPinter, अच्छी व्याख्या। मूल रूप से || = a = b या c नहीं है, मैंने देखते ही टोक दिया xyz||=true। यह कह रहा है कि यह शून्य है, यह हमेशा सच है। अगर यह सच है, यह सच है।
डेमन अव

7
हर कोई कह रहा है कि यह कितना बुरा scope ||= trueहै, मुझे आश्चर्य है कि किसी ने भी यह उल्लेख नहीं किया कि ऐसा करने का बेहतर तरीका क्या है scope = LDAP::LDAP_SCOPE_SUBTREE if scope.nil?। बेशक, यहां तक ​​कि यह मान रहा है कि nilएक अमान्य मूल्य है।
एरिक सैंडबर्ग

1
इस ओल्डी को अपडेट करें: एक विकल्प अंडरस्कोर नोटेशन का उपयोग करना है। दुर्भाग्य से, यह पैरामीटर को सेट करने के समान प्रभाव है nil। कुछ को यह ldap_get(base_dn, filter, _, X)नोट पसंद आ सकता है: (नोट: मुझे नहीं पता (अभी तक) यह कब रूबी में पेश किया गया था। दिलचस्प SO थ्रेड )।
एरिक प्लैटन

137

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

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

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

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

7
मैं इसे हतोत्साहित करता हूं क्योंकि विकल्प आपको यह नहीं बताते हैं कि विधि क्या अपेक्षा करती है या डिफ़ॉल्ट मान क्या हैं
ब्रॉन डेविस

53

समय आगे बढ़ गया है और संस्करण 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"

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

3

इसे आपके द्वारा परिभाषित किए गए तरीके से करना संभव नहीं है ldap_get। हालाँकि, यदि आप ldap_getइस तरह परिभाषित करते हैं:

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

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

ldap_get( base_dn, filter, X )

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

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


1

1) आप विधि को अधिभार नहीं डाल सकते हैं ( क्यों माणिक समर्थन विधि अधिभार नहीं है? ) तो पूरी तरह से एक नई विधि क्यों नहीं लिखनी चाहिए?

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


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

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

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, फ़िल्टर और अटार्स और param_array को सौंपा होगा [] जब 4 और अधिक तर्क होंगे तो param_array [तर्क 1, or_more, और_more] होगा

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

एक और चीज जो आपको करनी है वह है गुंजाइश के डिफ़ॉल्ट मान को फिर से लिखना।


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

3
-1: एरिक सही है। Irb 2.0.0p247 में एक सिंटैक्स त्रुटि का कारण बनता है। द रूबी प्रोग्रामिंग लैंग्वेज के अनुसार , रूबी 1.8 में स्पैट पैरामीटर एक को छोड़कर अंतिम होना चाहिए था &parameter, लेकिन रूबी 1.9 में इसके बाद "साधारण पैरामीटर" भी हो सकता है। न तो मामले में एक पैरामीटर के साथ एक डिफ़ॉल्ट कानूनी के साथ एक पैरामीटर था जो एक छींट के साथ था।
andyg0808

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

इसलिए एंडीजी सही है, इसके लिए आदेश की आवश्यकता है: डीएडी l_ap_get (base_dn, filter, attrs = nil, * param_array)
Rsweb

-1

आप इसे आंशिक अनुप्रयोग के साथ कर सकते हैं, हालांकि नामित चर का उपयोग निश्चित रूप से अधिक पठनीय कोड की ओर जाता है। जॉन रेसिग ने 2008 में जावास्क्रिप्ट में कैसे करें के बारे में एक ब्लॉग लेख लिखा: 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);
  };
};

संभवतः रूबी में एक ही सिद्धांत को लागू करना संभव होगा (प्रोटोटाइप विरासत के अलावा)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.