如何传递参数

时间:2018-11-22 11:48:51

标签: ruby

我可以创建将位置和关键字参数的任意组合传递给另一种方法的方法吗?

此版本在所有情况下均不起作用:

def proxy(*args, **keywords)
  send(yield, *args, **keywords)
end

def foo1(param)
  puts 'foo1', param
end

def foo2(params:)
  puts 'foo2', params
end

def foo3(param, params:)
  puts 'foo3', param, params
end

def foo4()
  puts 'foo4'
end


proxy('param') { 'foo1' } #1
proxy(params: 'params') { 'foo2' } #2
proxy('param', params: 'params') { 'foo3' } #3
proxy { 'foo4' } #4

#2和#3正在工作。

#1加注wrong number of arguments (given 2, expected 1) (ArgumentError)

#4加注wrong number of arguments (given 1, expected 0) (ArgumentError)

2 个答案:

答案 0 :(得分:1)

您可以尝试:

def proxy(*args)
  send(yield, *args)
end

[24] pry(main)> proxy('param') { 'foo1' } #1
foo1
param
=> nil
[25] pry(main)> proxy(params: 'params') { 'foo2' } #2
foo2
params
=> nil
[26] pry(main)> proxy('param', params: 'params') { 'foo3' } #3
foo3
param
params
=> nil
[27] pry(main)> proxy { 'foo4' } #4
foo4

答案 1 :(得分:0)

您在上面使用两种不同类型的参数,关键字参数和位置参数。可以在以下位置找到有关差异的很好描述:

https://robots.thoughtbot.com/ruby-2-keyword-arguments

使用他们给出的示例:

def mysterious_total(subtotal, tax, discount)
  subtotal + tax - discount
end

mysterious_total(100, 10, 5) # => 105

上面是一个有效的方法,但是在调用它时,如果不查看方法本身的定义,就不会真正知道放置参数的位置。如果小计并以错误的方式计税,您将得到错误的结果。关键字参数通过说明参数名称来防止这种情况:

def obvious_total(subtotal:, tax:, discount:)
  subtotal + tax - discount
end

obvious_total(subtotal: 100, tax: 10, discount: 5) # => 105

我认为这是更好的方法,尽管并非每个红宝石编码人员都同意。这样,您可以在不中断方法的情况下重新排列参数,并且无论您在何处阅读该方法都有意义。如果要使用其中一些可选功能,可以执行以下操作:

def obvious_total(subtotal: 100, tax: 10, discount: 5)
  subtotal + tax - discount
end

如果您现在只调用obvious_total而没有任何参数,它将使用您提供的默认参数,并且可以仅使用一个参数obvious_total(subtotal: 200)进行调用 使用放置参数进行此操作要困难得多,因为代码不知道您缺少哪个参数。使用第一个示例:

def mysterious_total(subtotal = 100, tax = 10, discount = 5)
  subtotal + tax - discount
end

如果我只是打电话给mysterious_total(100),则系统不知道我遗漏了哪个参数

最后,在同一方法定义中混合使用位置参数和关键字参数是不好的做法。进一步阅读:

https://makandracards.com/makandra/36011-ruby-do-not-mix-optional-and-keyword-arguments