Ruby 双splat在方法调用中做什么?
在准备的过程中,我解决了问题,遇到了这样一个场景:Ruby 双splat在方法调用中做什么?,ruby,double-splat,Ruby,Double Splat,在准备的过程中,我解决了问题,遇到了这样一个场景: def add(x:, y:, **params) z = x + y params[:round] ? z.round : z end p add(x: 3, y: 4) #=> 7 // no surprise here p add(x: 3.75, y: 3, round: true) #=> 7 // makes total sense options = {:round => true}; p add(
def add(x:, y:, **params)
z = x + y
params[:round] ? z.round : z
end
p add(x: 3, y: 4) #=> 7 // no surprise here
p add(x: 3.75, y: 3, round: true) #=> 7 // makes total sense
options = {:round => true}; p add(x: 3.75, y: 3, **options) #=> 7 // huh?
现在,我知道如何使用双splat将参数中的参数转换为散列,例如:
def splat_me(a, *b, **c)
puts "a = #{a.inspect}"
puts "b = #{b.inspect}"
puts "c = #{c.inspect}"
end
splat_me(1, 2, 3, 4, a: 'hello', b: 'world')
#=> a = 1
#=> b = [2, 3, 4]
#=> c = {:a=>"hello", :b=>"world"}
然而,我也知道,你不能随机加倍splat
options = {:round => true}
**options
#=> SyntaxError: (irb):44: syntax error, unexpected **arg
#=> **options
#=> ^
问题: 在方法调用(而不是定义)中,双splat(
***
)有什么用途
简单地说,这是什么时候:
options = {:round => true}; p add(x: 3.75, y: 3, **options)
比这更好的是:
options = {:round => true}; p add(x: 3.75, y: 3, options)
编辑:测试双splat的有用性(未找到) Args有或没有都是一样的
def splat_it(**params)
params
end
opts = {
one: 1,
two: 2,
three: 3
}
a = splat_it(opts) #=> {:one=>1, :two=>2, :three=>3}
b = splat_it(**opts) #=> {:one=>1, :two=>2, :three=>3}
a.eql? b # => true
我的意思是,您甚至可以毫无问题地将哈希传递给使用关键字params定义的方法,它将智能地分配适当的关键字:
def splat_it(one:, two:, three:)
puts "one = #{one}"
puts "two = #{two}"
puts "three = #{three}"
end
opts = {
one: 1,
two: 2,
three: 3
}
a = splat_it(opts) #=> {:one=>1, :two=>2, :three=>3}
#=> one = 1
#=> two = 2
#=> three = 3
b = splat_it(**opts) #=> {:one=>1, :two=>2, :three=>3}
#=> one = 1
#=> two = 2
#=> three = 3
在一个随机类上使用适当的to_h
和to_hash
方法进行双重splat不会做没有它就做不到的事情:
Person = Struct.new(:name, :age)
Person.class_eval do
def to_h
{name: name, age: age}
end
alias_method :to_hash, :to_h
end
bob = Person.new('Bob', 15)
p bob.to_h #=> {:name=>"Bob", :age=>15}
def splat_it(**params)
params
end
splat_it(**bob) # => {:name=>"Bob", :age=>15}
splat_it(bob) # => {:name=>"Bob", :age=>15}
可能需要对输入参数进行分解。在这种情况下,简单的哈希将不起作用:
params = {foo: 42, bar: :baz}
def t1(foo:, **params); puts params.inspect; end
#⇒ :t1
def t2(foo:, params); puts params.inspect; end
#⇒ SyntaxError: unexpected tIDENTIFIER
def t2(params, foo:); puts params.inspect; end
#⇒ :t2
现在让我们测试一下:
t1 params
#⇒ {:bar=>:baz}
t2 params
#⇒ ArgumentError: missing keyword: foo
t2 **params
#⇒ ArgumentError: missing keyword: foo
也就是说,双splat允许透明的参数解构
如果有人想知道为什么它可能有用,那么在上面的示例中,foo
在这个语法中的方法调用中成为一个强制参数
允许在函数调用中取消晶格参数,作为一种健全类型检查,以确保所有键都是符号:
h1 = {foo: 42}
h2 = {'foo' => 42}
def m(p); puts p.inspect; end
m **h1
#⇒ {:foo=>42}
m **h2
#⇒ TypeError: wrong argument type String (expected Symbol)
您好,是的,我知道它在定义方法时是多么有用。问题是,它在调用方法时如何有用。也就是说,
t2**params
什么时候有用?这是一种确保所有键都是符号的方法<代码>**{foo'=>42}将引发。有点像类型检查。不确定它是否回答了你的问题,但我的同事昨天与我的团队分享了这篇文章。里面有一些有趣的东西!谢谢@Nate,虽然这是一篇很棒的文章,但它并没有提到在调用方法时使用双splat,这正是我感兴趣的。我知道splats和double splats的所有用法:)不管怎样,这本书读起来很有趣,谢谢分享!是的,我后来意识到了这一点,但我想这可能会有所帮助。真高兴!