Ruby isteğe bağlı parametreler


121

Bir Ruby işlevini şöyle tanımlarsam:

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

Nasıl sadece ilk 2 ve son argümanları sağlayan diyebilirim? Neden bir şey değil

ldap_get( base_dn, filter, , X)

mümkün ya da mümkünse nasıl yapılabilir?

Yanıtlar:


131

Şu anda Ruby ile bu mümkün değil. Yöntemlere 'boş' öznitelikler geçiremezsiniz. Alabileceğiniz en yakın şey nil'i geçmek:

ldap_get(base_dn, filter, nil, X)

Ancak bu, kapsamı LDAP :: LDAP_SCOPE_SUBTREE değil, nil olarak ayarlar.

Yapabilecekleriniz, yönteminiz içinde varsayılan değeri ayarlamaktır:

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

Şimdi yöntemi yukarıdaki gibi çağırırsanız, davranış beklediğiniz gibi olacaktır.


21
Bu yöntemle biraz anladım: örneğin scopetrue için varsayılan değeri yapmaya çalışıyorsanız ve siz geçerseniz false, scope ||= trueişe yaramayacaktır. Aynı şeyi değerlendiriyor nilve ayarlayacaktrue
Joshua Pinter

4
Bu cevaptan 3 yıl sonra Ruby'nin şu anki versiyonuyla mümkün mü?
dalloliogm

1
@JoshPinter, güzel açıklama. Temelde || = a = b veya c değil, görmekten korktum xyz||=true. Eğer sıfırsa, her zaman doğrudur diyor. Eğer doğruysa, doğrudur.
Damon Aw

7
Herkes ne kadar kötü scope ||= trueolduğunu söylerken , kimsenin bunu yapmanın daha iyi yolunun bundan bahsetmemesine şaşırdım scope = LDAP::LDAP_SCOPE_SUBTREE if scope.nil?. Tabii ki, bu bile nilgeçersiz bir değer olduğunu varsayıyor .
Erik Sandberg

1
Bu eski sürüm için güncelleme: Bir alternatif, alt çizgi gösterimini kullanmaktır. Ne yazık ki, parametrenin ayarlanmasıyla aynı etkiye sahiptir nil. Bazıları şu notasyonu beğenebilir: ldap_get(base_dn, filter, _, X)(not: Bunun Ruby'de ne zaman tanıtıldığını (henüz) bilmiyorum. İlginç SO dizisi ).
Eric Platon

137

Bir seçenek karması kullanmanız neredeyse her zaman daha iyidir.

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

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

23
Yaygın bir strateji, varsayılan seçenekler karma değerine sahip olmak ve geçirilen her şeyi birleştirmektir:options = default_options.merge(options)
Nathan Long

7
Bunu cesaretlendirmiyorum çünkü seçenekler size yöntemin ne beklediğini veya varsayılan değerlerin ne olduğunu söylemiyor
Bron Davies

53

Zaman ilerledi ve sürüm 2 Ruby adlandırılmış parametreleri desteklediğinden beri:

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
Ek tanımsız anahtar kelime argümanları toplamak için çift işaret de kullanabilirsiniz. Bu, şu sorunla ilgilidir: stackoverflow.com/a/35259850/160363
Henry Tseng

3

Bunu tanımladığınız şekilde yapmanız mümkün değil ldap_get. Ancak, böyle tanımlarsanız ldap_get:

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

Şimdi yapabilirsin:

ldap_get( base_dn, filter, X )

Ama şimdi ilk iki argüman ve son argüman ile arayamama probleminiz var (önceki ile aynı problem ama şimdi son argüman farklı).

Bunun mantığı basittir: Ruby'deki her argümanın varsayılan bir değeri olması gerekmez, bu nedenle bunu belirttiğiniz gibi arayamazsınız. Sizin durumunuzda, örneğin, ilk iki bağımsız değişkenin varsayılan değerleri yoktur.


1

1) Yöntemi aşırı yükleyemezsiniz ( Ruby yöntemin aşırı yüklenmesini neden desteklemiyor? ) Öyleyse neden tamamen yeni bir yöntem yazmıyorsunuz?

2) Sıfır veya daha fazla uzunlukta bir dizi için uyarma operatörünü * kullanarak benzer bir sorunu çözdüm. Daha sonra, yapabileceğim bir parametreyi iletmek istersem, bu bir dizi olarak yorumlanır, ancak yöntemi herhangi bir parametre olmadan çağırmak istersem, hiçbir şey iletmem gerekmez. Bkz Yakut Dili Programlama sayfaları 186/187


0

Son zamanlarda bunun üstesinden gelmenin bir yolunu buldum. Dizideki öğeleri tutmak veya atmak için isteğe bağlı bir parametre ile dizi sınıfında bir yöntem oluşturmak istedim.

Bunu simüle etme şeklim, parametre olarak bir dizi geçirip bu dizindeki değerin sıfır olup olmadığını kontrol etmekti.

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

Sınıf yöntemimizi farklı parametrelerle denemek:

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)

çıktı: ["1", "2", "a", "b", "c"]

Tamam, planlandığı gibi çalışan harika. Şimdi dizideki üçüncü parametre seçeneğini (1) geçmezsek ne olacağını kontrol edelim.

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)

çıktı: ["a", "b", "c"]

Gördüğünüz gibi, dizideki üçüncü seçenek kaldırıldı, böylece yöntemde farklı bir bölüm başlatılıyor ve aralığımızda olmayan tüm ASCII değerleri kaldırılıyor (32-126)

Alternatif olarak, değeri parametrelerde sıfır olarak verebilirdik. Aşağıdaki kod bloğuna benzer görünür:

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

Mümkün :) Sadece tanımı değiştirin

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

için

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

kapsam şimdi ilk sırada dizide olacaktır. 3 bağımsız değişken sağladığınızda, temel_dn, filtre ve öznitelik atamış olursunuz ve param_array [] olur 4 ve daha fazla bağımsız değişken olduğunda, param_array [bağımsız değişken1 veya daha fazla ve_daha fazla] olur

Dezavantajı ise ... çözümü belirsiz, gerçekten çirkin. Bu, ruby'de işlev çağrısının ortasında argümanın çıkarılmasının mümkün olduğunu yanıtlamak içindir :)

Yapmanız gereken başka bir şey de varsayılan kapsam değerini yeniden yazmaktır.


4
Bu çözümler tamamen yanlış. attrs=nilBir splat ( *param_array) sonrasında varsayılan bir değer parametresi ( ) kullanmak bir sözdizimi hatasıdır .
Erik Sandberg

3
-1: Erik haklı. İrb 2.0.0p247'de sözdizimi hatasına neden olur. Göre Dili Programlama Ruby , Ruby 1.8 içinde uyarısı parametresi bir haricinde son gerekiyordu &parameterama Ruby 1.9 o "sıradan parametreler" de takip edilebilir. Her iki durumda da uyarılı bir parametreden sonra varsayılan geçerli olan bir parametre değildi.
andyg0808

Ruby Programlama Dili sayfa 186/187 uyarının yöntemlerle kullanılması uygundur. & Kullanılmadıkça, yöntemdeki son parametre olmalıdır.
rupweb

Yani AndyG haklı, sıranın şöyle olması gerekiyor: def ldap_get (base_dn, filter, attrs = nil, * param_array)
rupweb

-1

Bunu kısmi uygulamayla yapabilirsiniz, ancak adlandırılmış değişkenlerin kullanılması kesinlikle daha okunabilir koda yol açar. John Resig, bunun JavaScript'te nasıl yapılacağı hakkında 2008'de bir blog makalesi yazdı: 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);
  };
};

Muhtemelen aynı prensibi Ruby'de de uygulamak mümkün olacaktır (prototip kalıtım dışında).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.