如何确定Ruby中是否传递了可选参数
如果我在Ruby中有以下方法:如何确定Ruby中是否传递了可选参数,ruby,parameters,optional-parameters,Ruby,Parameters,Optional Parameters,如果我在Ruby中有以下方法: def foo(arg1, arg2 = "bar") puts arg1 puts arg2 end 是否有办法确定用户是否在方法中为arg2传递了值?显然,如果arg2==“bar”,我可以只向方法中添加,但这不包括用户自己手动输入“bar”的情况。当然,我可以将默认设置为任何用户都不会传入的内容,但很快就会变得非常糟糕 外面有什么优雅的东西吗?我不确定这是否可行。考虑以下事项: def foo(*args) case args.length
def foo(arg1, arg2 = "bar")
puts arg1
puts arg2
end
是否有办法确定用户是否在方法中为arg2
传递了值?显然,如果arg2==“bar”,我可以只向方法中添加,但这不包括用户自己手动输入“bar”
的情况。当然,我可以将默认设置为任何用户都不会传入的内容,但很快就会变得非常糟糕
外面有什么优雅的东西吗?我不确定这是否可行。考虑以下事项:
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
class Test
def method(a,b=1)
local_variables.each do |var|
puts "Setting #{var} to #{eval var.to_s}"
end
end
end
raise ArgumentError, "Too many arguments" if args.length > 2
然后尝试在Test
的实例上调用method
:
?> 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的方法结合以下内容:
class Test
def method(a,b=1)
local_variables.each do |var|
puts "Setting #{var} to #{eval var.to_s}"
end
end
end
raise ArgumentError, "Too many arguments" if args.length > 2
因为您似乎希望将参数限制为2,@sawa的方法允许使用未定义的数字
这是一种针对非正统需求的非正统方法,因此只需确保方法的客户端了解API的工作原理。一种方法(不是优雅而是有趣)是设置默认值,使其具有唯一的对象id
。如果默认值是不可变的对象(如integer),则它将不起作用
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"
我有一个解决办法!假设我们想要:
def foo(arg1, arg2 = 42)
然后我们会写:
def foo(arg1, arg2 = [42,KEY])
如果agr2==[42,KEY]
,我们得出结论,调用方法没有传递第二个参数,在这种情况下,默认值42
适用。如果arg2
是其他内容,则传递arg2
。简单
我知道你在想什么:如果调用程序真的通过了[42,KEY]
?我也弄明白了:KEY=rand(1000000000000)
我想补充一点。原则上,我反对这样做,但我知道如果我不这样做,我会收到太多的反对票,我的声誉将受到负面影响。所以这里是::-)我的理解正确吗,例如,您想知道foo
是否可以确定对它的调用是foo(arg1)
还是foo(arg1,“bar”)
?是的,就是这样。感谢您提供的详细信息。在我的实际实现中,我只是将第二个参数默认为nil
(因为用户永远不会将nil
传递给它),然后在方法中用“default”值交换nil
,但我很好奇是否有更好的方法。我不明白为什么要反复使用局部变量,而不仅仅是引用a
和b
。不管怎样,这不就是我们已经知道的吗?我喜欢!这就是Rubinius在许多方法实现中所做的。在YARV、JRuby等中,它们是用C、Java等实现的,可以访问参数列表的内部实现,因此可以检查传递了多少个参数。但是在Rubinius中,这些方法中的许多都是用纯Ruby实现的,没有任何特殊的功能,因此它们不得不求助于这样的技巧。在Rubinius中,有一个特殊的undefined
方法,该方法返回一个具有不可伪造object\u id
的对象,然后在该方法中执行undefined.equals?(b)
。有趣;如果您能帮助理解a=(b=true;“something”)
这只是一个Ruby表达式,我将不胜感激。它首先将b
设置为true
,然后作为新语句执行字符串“something”
。整个括号的值将是最后一条语句的值,因此它仍然会按预期将a
设置为“something”
。我相信你希望这是arg2=(arg2\u was\u passed=false;“bar”)
,但不是true
。这是天才!我只是想了一下类似的方法,发现你已经回答了。我想知道你为什么反对使用这种方法。例如,编写像def mymethod(param1,param2=“未由用户指定”)
这样的方法有什么坏处?如果param2==“未由用户指定”
,则我可以在正文中使用param2=“default value”。原则上我没有异议(尽管其他人可能会反对)。我只是觉得这有点含糊不清,最好是重新构造代码,避免回答这个问题。