While designing an api I notice that double splats can’t be used after named arguments. I am not sure if there is a reason to not allow them.
The api I was defining can be reduced to
def named(*, name, **opts)
generic(name: name, **opts) # Error: expected named argument, not **
end
def generic(**opts)
opts.to_h
end
puts named(name: "Stuart", fruit: "banana")
It was more natural to me to write generic(name: name, **opts)
but that does not work: Error: expected named argument, not **
Using generic(**opts, name: name)
works just fine. As well as manually creating the arguments via named tuple merge args = {name: name}.merge(opts);generic(**args)
.
Is there a fundamental reason to disallow double splats after named arguments?
I think I missed that case when I implemented it. It should be relatively easy to implement this. Let me know if you’d like me to give it a try.
I noticed this last week or so, too. I wasn’t super bothered, but I was surprised. It’s nice to know it wasn’t an intentional decision and that it can be implemented relatively easily! 
It turns out this is already possible. However, named arguments must come after the double splat:
def named(*, name, **opts)
generic(**opts, name: name) # No error!
end
def generic(**opts)
opts.to_h
end
puts named(name: "Stuart", fruit: "banana")
I think the reason is that **opts
is represented in the compiler as an argument more that’s double splatting, and named argument must come after regular arguments, never before.
In fact, you can specify a double splat multiple times:
def named(*, name, **opts)
more_opts = {foo: 1}
generic(**opts, **more_opts, name: name) # No error!
end
def generic(**opts)
opts.to_h
end
puts named(name: "Stuart", fruit: "banana")
I think that’s what Brian was saying 
Oooh… I didn’t read that part 
Well, that’s my answer 
It seems in Ruby you can put them in any other… it’s just a bit more annoying to implement that way, but it’s totally possible.
1 Like
This seems reasonable to be the cause of the (unintended) limitation.
It’s not a stopper issue. And building the named tuple manually allows overriding value which **opts, name: name
will (and should) not.
I think is more natural/reasonable to write m(name: name, **opts)
. But there is no rush to have that.
Although it could be implemented, another option is to change the error message for this case.