【问题标题】:How to decide whether an optional argument was given or not in a ruby method如何确定是否在 ruby​​ 方法中给出了可选参数
【发布时间】:2012-02-01 02:04:52
【问题描述】:

我有一个带有可选参数的方法。我如何确定是否给出了参数?

我想出了以下解决方案。我问这个问题是因为我对其中任何一个都不完全满意。还有更好的吗?

nil 作为默认值

def m(a= nil)
    if a.nil?
        ...
    end
end

这个的缺点是,无法确定是没有参数还是nil

自定义NoArgument作为默认值

class NoArgument
end

def m(a= NoArgument.new)
    if NoArgument === a
        ...
    end
end

nil 是否给出可以判断,但NoArgument 的实例存在同样的问题。

评估省略号的大小

def m(*a)
    raise ArgumentError if m.size > 1
    if m.size == 1
        ...
    end
end

在这个变体中,总是可以决定是否给出了可选参数。 但是,此方法的 Proc#arity 已从 1 更改为 -1(不正确,请参阅评论)。它仍然有一个缺点是记录更糟并且需要手动引发 ArgumentError。

【问题讨论】:

  • 所有方法中的arity-1。最后一个解决方案的唯一缺点是您必须手动检查是否给出了不超过一个参数,并且需要文档才能知道参数是什么。

标签: ruby optional-parameters


【解决方案1】:

Jorg W Mittag 有 following code snippet 可以做你想做的事:

def foo(bar = (bar_set = true; :baz))
  if bar_set
    # optional argument was supplied
  end
end

【讨论】:

  • 这个的用例是什么?
  • @AndrewF:johannes 或 Jorg W Mittag 会更好地回答这个问题。
  • 核心库中的一些方法会根据提供的参数数量而有所不同。实际上,它们模拟了基于参数的调度。在大多数 Ruby 实现中,这些方法是用 C、C++、Java、C# 等实现的,并且它们具有访问 Ruby 内部的特权,因此它们可以实际上只是检查参数的数量。但是,如果你想在 Ruby 中编写一个兼容的方法,你就不得不求助于这样的技巧。
  • 我认为反之亦然。您的 bar_set 变量仅在 Ruby 必须计算出参数的默认值时设置,因此当未给出 bar 时,它实际上设置为 true。也许变量应该命名为bar_omitted
【解决方案2】:

怎么样

NO_ARGUMENT = Object.new

def m(a = NO_ARGUMENT)
    if a.equal?(NO_ARGUMENT)
        #no argument given
    end
end

【讨论】:

  • 例如,这是Rubinius采用的方法。
  • 这种方法的唯一缺点是该方法可能决定将NO_ARGUMENT 作为参数传递给使用此习惯用法的另一个方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 2013-06-05
  • 2011-01-21
  • 1970-01-01
相关资源
最近更新 更多