Ruby 如何传递send方法的所有参数 问题
在一个方法中,如何将作为发送方法的一部分提供的所有参数传递给另一个发送方法?所有参数的命名都应该考虑到没有像Ruby 如何传递send方法的所有参数 问题,ruby,Ruby,在一个方法中,如何将作为发送方法的一部分提供的所有参数传递给另一个发送方法?所有参数的命名都应该考虑到没有像*args这样的占位符/捕捉器,但它们可以是关键字参数和非关键字参数的组合。此外,内部方法send不是super 示例(伪代码) def some_方法(一个_参数,一个名为_参数:) …做点什么。。。 某些\u其他\u方法([使用原始参数发送]) …做点别的。。。 终止 相关问题 7年前被问过 丑陋的黑客 根据我的发现,可以对关键字参数执行如下操作: def some_method(a
*args
这样的占位符/捕捉器,但它们可以是关键字参数和非关键字参数的组合。此外,内部方法send不是super
示例(伪代码)
def some_方法(一个_参数,一个名为_参数:)
…做点什么。。。
某些\u其他\u方法([使用原始参数发送])
…做点别的。。。
终止
相关问题
7年前被问过
丑陋的黑客
根据我的发现,可以对关键字参数执行如下操作:
def some_method(a_named_parameter:, another_named_parameter:)
...do something...
params = method(__method__)
.parameters
.map { |p| [p[1], binding.local_variable_get(p[1])] }
.to_h
some_other_method(**params)
...do something else...
end
def some_method(a_named_parameter, another_named_parameter)
...do something...
params = method(__method__)
.parameters
.map { |p| binding.local_variable_get(p[1]) }
some_other_method(*params)
...do something else...
end
对于非关键字参数:
def some_method(a_named_parameter:, another_named_parameter:)
...do something...
params = method(__method__)
.parameters
.map { |p| [p[1], binding.local_variable_get(p[1])] }
.to_h
some_other_method(**params)
...do something else...
end
def some_method(a_named_parameter, another_named_parameter)
...do something...
params = method(__method__)
.parameters
.map { |p| binding.local_variable_get(p[1]) }
some_other_method(*params)
...do something else...
end
根据方法(\uuu method\uuu)返回的信息。参数
也可以找到一个对这两种方法都有效的解决方案,但即使可以将所有这些都提取到一个助手中,这也是一种复杂的方法。也许你的意思是这样的
def some_method *args, **kwargs, &block
...
some_other_method(*args, **kwargs, &block)
...
end
但是我认为在一些其他方法上使用方法委托更干净
也许你的意思是这样的
def some_method *args, **kwargs, &block
...
some_other_method(*args, **kwargs, &block)
...
end
但我认为在
某些其他方法上使用方法委派更为简洁,只是出于好奇,您可能需要以下帮助:
出于好奇,您可能需要以下帮助:
这是一个非常有趣的问题,所以首先,谢谢你
假设Binding
是一个对象,与其他任何对象一样,我们可以构建一个类来提供这种类型的功能,并利用原始方法的绑定将所有参数委托给下一个方法,如下所示:
class ArgsBuilder
attr_reader
def initialize(b)
@standard_args, @kwargs = [],{}
@binding = b
build!
end
def delegate(m)
@binding.receiver.send(m,*@standard_args,**@kwargs,&@block)
end
private
def build!
set_block(&@binding.eval('Proc.new')) if @binding.eval('block_given?')
@binding.eval('method(__method__)')
.parameters.each do |type,name|
next if type == :block
val = @binding.local_variable_get(name)
if type =~ /key/
@kwargs.merge!(type == :keyrest ? val : {name => val})
else
type == :rest ? @standard_args.concat(val) : @standard_args << val
end
end
end
def set_block(&block)
@block = block
end
end
似乎很简单,可以作为一个助手,处理通过方法传递的命名块和匿名块
TL;DR
这显然需要在委托方法中匹配或至少接受类似签名,类似于super
的工作方式。然而,我们可以进一步采取这一步骤,为参数类型创建类[:req,:opt,:rest,:keyreq,:key,:keyrest,:block]
将它们放入一个集合中,然后询问委托给它们的方法,以确定要通过的正确参数;然而,我不确定这种类型的例子是否适合SO职位
附加说明:因为build在initialize
中调用code>,局部变量绑定在ArgsBuilder
类的实例化点是静态的。e、 g
def foo(n)
builder = ArgsBuilder.new(binding)
n = 17
builder.delegate(:bar)
end
def bar(n)
n
end
foo(42)
#=> 42
然而
def foo(n)
n = 17
ArgsBuilder.new(binding).delegate(:bar)
end
foo(42)
#=> 17
这并不意味着可变对象无法更改
def foo(n)
builder = ArgsBuilder.new(binding)
n.upcase!
builder.delegate(:bar)
end
foo('a')
#=> "A"
显然,您可以通过将调用移动到build代码>这是一个非常有趣的问题,所以首先,谢谢你
假设Binding
是一个对象,与其他任何对象一样,我们可以构建一个类来提供这种类型的功能,并利用原始方法的绑定将所有参数委托给下一个方法,如下所示:
class ArgsBuilder
attr_reader
def initialize(b)
@standard_args, @kwargs = [],{}
@binding = b
build!
end
def delegate(m)
@binding.receiver.send(m,*@standard_args,**@kwargs,&@block)
end
private
def build!
set_block(&@binding.eval('Proc.new')) if @binding.eval('block_given?')
@binding.eval('method(__method__)')
.parameters.each do |type,name|
next if type == :block
val = @binding.local_variable_get(name)
if type =~ /key/
@kwargs.merge!(type == :keyrest ? val : {name => val})
else
type == :rest ? @standard_args.concat(val) : @standard_args << val
end
end
end
def set_block(&block)
@block = block
end
end
似乎很简单,可以作为一个助手,处理通过方法传递的命名块和匿名块
TL;DR
这显然需要在委托方法中匹配或至少接受类似签名,类似于super
的工作方式。然而,我们可以进一步采取这一步骤,为参数类型创建类[:req,:opt,:rest,:keyreq,:key,:keyrest,:block]
将它们放入一个集合中,然后询问委托给它们的方法,以确定要通过的正确参数;然而,我不确定这种类型的例子是否适合SO职位
附加说明:因为build在initialize
中调用code>,局部变量绑定在ArgsBuilder
类的实例化点是静态的。e、 g
def foo(n)
builder = ArgsBuilder.new(binding)
n = 17
builder.delegate(:bar)
end
def bar(n)
n
end
foo(42)
#=> 42
然而
def foo(n)
n = 17
ArgsBuilder.new(binding).delegate(:bar)
end
foo(42)
#=> 17
这并不意味着可变对象无法更改
def foo(n)
builder = ArgsBuilder.new(binding)
n.upcase!
builder.delegate(:bar)
end
foo('a')
#=> "A"
显然,您可以通过将调用移动到build代码>我不明白,你知道一些其他方法的签名。为什么不简单地写出它需要的所有参数呢?它简单易读,不需要魔法。当然是@SergioTulentsev,我通常也会这么做。但是考虑到调用super
是可能的,而且我发现这非常方便,我想知道一般来说是否也可以这样做。我希望它不像黑客那样神奇。我明白了。我希望你能找到:)@SergioTulentsev我欢迎你对我的答案提出意见,因为我正在努力寻找我可能遗漏的边缘案例。我不明白,你知道某些其他方法的签名。为什么不简单地写出它需要的所有参数呢?它简单易读,不需要魔法。当然是@SergioTulentsev,我通常也会这么做。但是考虑到调用super
是可能的,而且我发现这非常方便,我想知道一般来说是否也可以这样做。我希望它不像黑客那样神奇。我明白了。我希望您能找到:)@SergioTulentsev我欢迎您对我的答案的输入,因为我正在尝试查找我可能遗漏的边缘案例。除了我们在某些方法的签名中丢失了所需的args/kwargs之外。@SergioTulentsev如果它们被修复,我们可以将它们塞进两个方法的签名中。是这样吗?事实上,我对这个问题并不确定。我想,这就是问题所在:“但是,考虑到打电话给super是可能的,而且我觉得非常方便,我想知道一般来说是否也可能。”。只对不相关的方法执行super
所做的操作。除了在某些方法的签名中丢失所需的args/kwargs之外。@SergioTulentsev如果它们是固定的,我们可以将它们塞进两个方法的签名中。是这样吗?我其实不太清楚