Ruby可选参数

如果我定义一个像这样的Ruby函数:

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

我怎么称呼它只提供第一个2和最后一个参数? 为什么不是这样的

 ldap_get( base_dn, filter, , X) 

可能或如果可能的话,怎么办?

目前这是不可能的。 您不能将“空”属性传递给方法。 你可以得到最接近的是通过零:

 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 

现在,如果你调用上面的方法,行为将如你所愿。

使用选项散列几乎总是更好。

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

时间已经过去,从版本2开始,Ruby支持命名参数:

 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" 

不可能按照您定义ldap_get的方式来执行此操作。 但是,如果您像这样定义ldap_get

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

现在你可以:

 ldap_get( base_dn, filter, X ) 

但现在你有问题,你不能用前两个参数和最后一个参数(与以前相同的问题,但现在的最后一个参数是不同的)调用它。

基本原理很简单:Ruby中的每个参数都不需要有默认值,所以你不能像你指定的那样调用它。 就你而言,例如,前两个参数没有默认值。

1)你不能重载方法( 为什么不用ruby支持方法重载? )为什么不写一个新的方法呢?

2)我使用splat运算符*解决了一个类似的问题,用于长度为零或更长的数组。 然后,如果我想传递一个参数,我可以将它解释为一个数组,但是如果我想调用没有任何参数的方法,那么我不必传递任何东西。 请参阅Ruby编程语言第186/187页

这是可能:)只是改变定义

 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,filter和attrs,而param_array将会是[]当4个或更多的参数,那么param_array将会是[argument1,or_more,and_more]

缺点是…不清楚的解决scheme,真的很难看。 这是回答,有可能在Ruby中的函数调用中间省略参数:)

你必须做的另一件事是重写范围的默认值。

最近我find了解决办法。 我想在数组类中使用可选参数创build一个方法来保留或放弃数组中的元素。

我模拟这个的方式是通过传递一个数组作为参数,然后检查该索引处的值是否为零。

 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 

你可以用部分应用程序来做到这一点,虽然使用命名variables肯定会导致更易读的代码。 John Resig在2008年写了一篇关于如何在JavaScript中使用的博客文章: 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); }; }; 

在Ruby中应用相同的原理也是可能的(除了原型inheritance)。