How to mix optional positional and named arguments?

Inspired by a StackOverflow question curious how correctly use
positional and named method/lambda/proc arguments.

Assume following method with both positional and named arguments
optional:

def meth(arg = {foo: 1}, kwarg: ‘bar’)
p arg, kwarg
end

Now I’d like to send meth with arg set to a different hash, kwarg leave
the default:

meth({foo:2})

ArgumentError: unknown keyword: foo

Surprisingly when hash argument has non-symbol key, it is taken as
positional as expected:

meth({‘foo’ = > 2})
{“foo”=>2}
“bar”
=> [{“foo”=>2}, “bar”]

By a trial-and-error I’ve figured out {foo: 2} can be “enforced” in
assignment to optional arg, when an extra empty hash is passed:

meth({foo:2},{})
{:foo=>2}
“bar”
=> [{:foo=>2}, “bar”]

Can somebody explain what’s going on here ?

Thanks.

Joan Blackmoore wrote in post #1176643:

By a trial-and-error I’ve figured out {foo: 2} can be “enforced” in
assignment to optional arg, when an extra empty hash is passed:

meth({foo:2},{})
{:foo=>2}
“bar”
=> [{:foo=>2}, “bar”]

An easier way would be to write

meth(*{foo:2})

Can somebody explain what’s going on here ?

I think we simply have a disambiguity here. Since ‘meth’ does accept
keyword arguments, Ruby assumes that one is passed here.

Maybe it’s more clear if you think about

meth({kwarg:0})

Is this supposed to mean that the positional parameter is supplied and
teh keyword parameter should take the default value, or the other way
around? Maybe the syntax of mixed arguments was not cleanly designed,
but in the way it is used now, Ruby has no choice here but to assume
that the key in the hash is a keyword argument.

Thanks.