如何确定Ruby中是否传递了可选参数

时间:2013-10-19 23:55:21

标签: ruby parameters optional-parameters

如果我在Ruby中使用以下方法:

def foo(arg1, arg2 = "bar")
  puts arg1
  puts arg2
end

有没有办法确定用户是否在方法中传递了arg2的值?显然我可以在方法中添加if arg2 == "bar",但这并不能解决用户自己手动传入"bar"的情况。当然,我可以将默认值设置为没有用户可以传递的内容,但是很快就会变得非常难看。

那里有什么优雅的东西吗?

5 个答案:

答案 0 :(得分:15)

def foo(arg1, arg2 = (arg2_not_passed = true; "bar"))
  puts arg1
  puts arg2
  puts 'arg2 was passed' unless arg2_not_passed
end

答案 1 :(得分:3)

def foo(*args)
  case args.length
  when 1
    # arg2 was not given
    arg1, arg2 = args.first, "bar"
    ...
  when 2
    # arg2 was given
    arg1, arg2 = args
    ...
  else
    raise ArgumentError
  end
end

答案 2 :(得分:3)

一种方式(不优雅但有趣)是使默认值具有唯一object_id。如果默认值是一个像整数这样的不可变对象,那么它将不起作用。

def c
  @c ||= "bar"
end

def fun(a,b = c)   
     puts  b.object_id == c.object_id ? "default" : "user" 
end

fun "foo"
#=> "default"

fun "foo", "bar"
#=> "user"

答案 3 :(得分:2)

我有一个解决方案!假设我们想:

def foo(arg1, arg2 = 42)

然后我们会写:

def foo(arg1, arg2 = [42,KEY])

如果agr2 == [42,KEY],我们得出结论,调用方法没有传递第二个参数,在这种情况下,默认值42适用。如果arg2是其他内容,则arg2已通过。简单!

我知道你在想什么:如果调用程序实际通过了[42,KEY]怎么办?我也想到了这一点:KEY = rand(100000000000000)

我想补充一点。我原则上反对这样做,但我知道如果我不这样做,我会收到这么多的支持,我的名声将会消极。所以这里是: - )

答案 4 :(得分:1)

我不确定这是可能的。请考虑以下事项:

class Test
  def method(a,b=1)
    local_variables.each do |var|
          puts "Setting #{var} to #{eval var.to_s}"
    end
  end
end

然后尝试在method

的实例上调用Test
?> t.method(1)
Setting a to 1
Setting b to 1
=> [:a, :b]

?> t.method(1,2)
Setting a to 1
Setting b to 2
=> [:a, :b]

?> t.method(1,1)
Setting a to 1
Setting b to 1
=> [:a, :b]

那些不区分方法的调用方式。

所以我建议@ sawa的方法与以下内容混合:

raise ArgumentError, "Too many arguments" if args.length > 2

因为您似乎想要将参数限制为2,而@ sawa的方法允许使用未定义的数字。

这是针对非正统要求的非正统方法,因此请确保您方法的客户了解API的工作原理。