【发布时间】:2019-01-25 01:22:47
【问题描述】:
在准备Ruby Association Certified Ruby Programmer Exam 时,我正在解决prep test 并遇到这种情况:
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?
现在,我知道如何使用 double-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"}
不过,我也知道,你不能随意双打。
options = {:round => true}
**options
#=> SyntaxError: (irb):44: syntax error, unexpected **arg
#=> **options
#=> ^
问题:
方法调用(不是定义)中的双标(**)有什么用?
说白了,这是什么时候:
options = {:round => true}; p add(x: 3.75, y: 3, **options)
比这更好:
options = {:round => true}; p add(x: 3.75, y: 3, options)
编辑:测试双板的实用性(未找到)
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
我的意思是,您甚至可以毫无问题地将哈希传递给使用关键字参数定义的方法,它会智能地分配适当的关键字:
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}
【问题讨论】:
-
不确定它是否能回答您的问题,但我的同事昨天与我的团队分享了这篇文章。里面有一些有趣的东西! blog.honeybadger.io/ruby-splat-array-manipulation-destructuring
-
感谢@Nate,虽然这是一篇很棒的文章,但它并没有谈到在 调用 方法时使用 double-splat,这是我感兴趣的。我知道那里详细介绍了 splats 和双 splats 的所有用途 :) 无论如何,这是一个有趣的阅读,感谢您的分享!
-
是的,后来我意识到了这一点,但我认为无论如何它可能会有所帮助。很高兴!
标签: ruby double-splat