Ruby 可选参数和多个参数

7

我正在尝试将方法的第一个参数设置为可选参数,然后是任意数量的参数。例如:

def dothis(value=0, *args)

我遇到的问题是似乎这是不可能的?当我调用dothis("hey", "how are you", "good")时,我希望它将值设置为默认值0,但实际上它只是使value="hey"。有没有办法实现这种行为?


你传递了第一个参数 "hey",它被分配给了 value。因此默认值无效。有什么问题吗? - sawa
我尝试实现的目标是保留value=0的值,并能够识别“hey”作为args的起始位置而不是value。这是因为我调用一个函数时,value的值大约90%的时间为0。但是偶尔需要变成1。这就是为什么我希望将其用作默认参数的原因。 - Andrew Backes
1
Ruby如何知道您传递的第一个参数是“value”还是“args”的第一个元素?你认为Ruby会读懂你的想法吗? - sawa
'value = 0' 这不是可选参数,而是默认值。 - user2107733
5
问题的关键是......是否存在其他实现这种行为的方法,或者它是不可能的。对于冒犯您,我感到抱歉...没必要表现敌意。 - Andrew Backes
4个回答

5

直接在 Ruby 中无法实现这一点。

不过,根据您对扩展参数的使用方式以及方法的预期功能,有很多选择可供使用。

显而易见的选择是

1)使用哈希语法获取命名参数

def dothis params
  value = params[:value] || 0
  list_of_stuff = params[:list] || []

Ruby在这方面的调用约定很好,您不需要提供哈希{}括号。
dothis :list => ["hey", "how are you", "good"]

2) 将值移动到结尾,并使用数组作为第一个参数

def dothis list_of_stuff, value=0

这样调用:

dothis ["hey", "how are you", "good"], 17

3) 使用代码块提供列表

dothis value = 0
  list_of_stuff = yield

这样调用

dothis { ["hey", "how are you", "good"] }

4) Ruby 2.0引入了命名哈希参数,可以为您处理上述选项1的很多内容:

def dothis value: 0, list: []
  # Local variables value and list already defined
  # and defaulted if necessary

同 (1) 一样调用:

dothis :list => ["hey", "how are you", "good"]

谢谢你的帮助。@Kyle,我也喜欢你的解决方案,但是我不确定是否想要命名参数的大块,因为在某些情况下,可能会有很多参数。不过,我肯定会尝试两种方法,并看看我更喜欢哪种方式。谢谢大家! - Andrew Backes
@adback03 没问题,我也更喜欢尼尔的解决方案 ;) - Kyle

3
这篇文章有点老,但如果有人正在寻找最佳解决方案,我想做出贡献。自从 Ruby 2.0 以来,你可以通过使用散列定义的命名参数轻松地实现这一点。语法简单易读。
def do_this(value:0, args:[])
   puts "The default value is still #{value}"
   puts "-----------Other arguments are ---------------------"
  for i in args
    puts i
  end
end
do_this(args:[ "hey", "how are you", "good"])

你也可以使用贪婪关键字 **args 来作为哈希表来完成相同的操作,如下所示:
#**args is a greedy keyword
def do_that(value: 0, **args)
  puts "The default value is still #{value}"
  puts '-----------Other arguments are ---------------------'
  args.each_value do |arg|
    puts arg
  end
end
do_that(arg1: "hey", arg2: "how are you", arg3: "good")

1
你需要使用命名参数来完成这个任务:
def dothis(args)
  args = {:value => 0}.merge args
end

dothis(:value => 1, :name => :foo, :age => 23)
 # => {:value=>1, :name=>:foo, :age=>23} 
dothis(:name => :foo, :age => 23)
 # => {:value=>0, :name=>:foo, :age=>23}

0

通过使用value=0,您实际上是将0分配给value。为了保留值,您可以使用上述提到的解决方案或每次调用此方法时简单地使用value def dothis(value,digit = [* args])。

默认参数在未提供参数时使用。

我遇到了类似的问题,并通过使用以下方式解决:

def check(value=0, digit= [*args])
puts "#{value}" + "#{digit}"
end 

而且只需像这样调用check:

dothis(value, [1,2,3,4])

你的值将会是默认值,其他的值属于其他参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接