123

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

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

我怎么能称它只提供前 2 个和最后一个 args?为什么不像

ldap_get( base_dn, filter, , X)

可能或如果可能,怎么做?

4

8 回答 8

137

使用选项哈希几乎总是更好。

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

ldap_get(base_dn, filter, :attrs => X)
于 2009-05-01T16:33:20.880 回答
131

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

ldap_get(base_dn, filter, nil, X)

但是,这会将范围设置为 nil,而不是 LDAP::LDAP_SCOPE_SUBTREE。

您可以做的是在您的方法中设置默认值:

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

现在,如果您按上述方式调用该方法,则行为将如您所愿。

于 2009-05-01T16:24:02.087 回答
54

时间已经过去了,从 Ruby 版本 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"
于 2014-07-14T19:00:27.660 回答
3

不可能按照您定义的方式进行ldap_get。但是,如果您ldap_get这样定义:

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

现在你可以:

ldap_get( base_dn, filter, X )

但是现在你有一个问题,你不能用前两个 args 和最后一个 arg 来调用它(和以前一样的问题,但现在最后一个 arg 不同了)。

这样做的理由很简单:Ruby 中的每个参数都不需要具有默认值,因此您不能按照您指定的方式调用它。例如,在您的情况下,前两个参数没有默认值。

于 2009-05-01T16:21:18.210 回答
1

1)你不能重载方法(为什么ruby不支持方法重载?)那么为什么不完全编写一个新方法呢?

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

于 2014-03-12T12:05:00.090 回答
0

最近我找到了解决这个问题的方法。我想在数组类中创建一个带有可选参数的方法,以保留或丢弃数组中的元素。

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

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)

或者,我们可以在参数中将值设为 nil。这看起来类似于以下代码块:

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
于 2014-01-28T18:53:47.133 回答
-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、filter 和 attrs 并且 param_array 将是 [] 当 4 个或更多参数时,param_array 将是 [argument1, or_more, and_more]

缺点是......解决方案不清楚,真的很难看。这是为了回答可以在 ruby​​ 中的函数调用中间省略参数:)

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

于 2010-11-09T13:50:30.150 回答
-1

您可以使用部分应用程序来做到这一点,尽管使用命名变量肯定会导致更易读的代码。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 中应用相同的原则(原型继承除外)。

于 2016-03-09T09:49:00.280 回答