I think the error message is clear that this is not supported right now, but it might be in the future. It’s not promising this ever going to happen, nor when.
There are currently no plans, and I don’t think there’s any priority on this one, considering nobody has ever asked for this before.
So my guess is your use cases is either very cornerish, or there could be other, more appropriate alternatives.
I understand “yet” merely indicates that this feature is theoretically possible and might be supported at a later time. But not if there are any concrete plans about it.
I thought it is for this reason that many libraries I have used directly support named_tuple as the args, instead of name keyword(which need splatting)
args = {
a: 100,
b: 200
}
so, instead of foo(**args), many library prefer to let users pass like foo(args), because use former is too easy to failed with double splatting a union issue as the example in my post.
If you know well the history of ruby, @matz said, because the initial design of keyword args with flaws, which cause Ruby pass a hash as options became a trend, and bringing a lot of pain when upgrading to Ruby 3 which try to support named keyword completely, those issue still not solved completely until now(ruby 3.3.2)
I don’t know how others use double splatting when passing args, but code like following failed frequently makes me very frustrated.
def foo(a, b, c = false)
p [a, b, c]
end
args = {
a: 1,
b: 2,
}
if rand(5) > 3
args = args.merge(c: true)
end
foo(**args)
# Error: double splatting a union (NamedTuple(a: Int32, b: Int32)
# | NamedTuple(a: Int32, b: Int32, g: Bool)) is not yet supported
It’s so common when write business logic, right?
I have never had this issue. Nor have there been any reports from users asking for this apart from yourself.
So I don’t think it’s a common use case.
What kind of report would you have expected for something the compiler tells us is a known issue?
Asking because I’ve run into this quite a few times. Mostly, I work around it exactly as @zw963 mentioned — coincidentally, some of my most notable use cases have been for HTML components to support HTMX, just not with Lucky. But I would never have reported it because the compiler tells us you already know about this limitation.
Having also never ran into this before, I think this is a fairly solvable problem without having to change the compiler. Is there a reason Lucky’s implementation couldn’t be setup to have a NamedTuple (or Hash) overload such that you could pass your args directly without having to double splat at all? Even if you have to do something like extra_args: args that would already be an improvement.
But this is another question anyway, why we limit the author of library must define another method overload to support passing NamedTuple Or Hash only because a long live bug in compiler still not fix YET?
This introduces unnecessary complexity for library authors obviously.
Does the core team not encourage us to use double splashing?
Isn’t using named keyword directly more clearer and more error friendly?
Why we introduce double splatting feature in Crystal?
The compiler knows about this bug, but as @straight-shoota said there are no plans to fix it. do you think anyone will still use double splatting after a few years? e.g. in version 2.0 ?
This is a bit of an exaggeration. It makes more sense to me to support both overloads as they serve different purposes. Like the **args version works great when I just want to add some extra args to the method call directly. E.g. input foo: "bar". But when you’re getting into building out some collection of args it makes more sense to be able to pass that collection directly.
It feels to me, double splatting in this context is more so a workaround for a missing API feature of the underlying lib than it is a use case to be able to double splat unions. Even then I would say it’s more of an unimplemented feature than a bug. I’d maybe bring this up in the Lucky repo, would be a pretty trivial change I’d imagine.
Disgree, none of above example tends to pass a collection into. the purpose of introduce a NamedTuple is just for the need of business logic, this is not something cornerish, it’s so common when use other language, there is no another better way to replace this.
use Named keyword with correct double splatting support is always preferred for use case like above input foo: "bar", why you want pass a collection as the only args for input tag attributes instead of (clearly) named keyword? that’s because as a user, I have to, because the not yet supported feature.
To be clear, the only thing I’m suggesting you do is like input(args) instead of input(**args). Your args named tuple is a collection type and is merely a container for holding key/value tag pairs. Looking closer at the source code, they already do seem to support this:
As there is an overload that accepts only options, plus extra one-off named args. So if you stop trying to double splat your args, and just pass it as the collection type it is, it should just work as long as you can be assured the value of each item is a String.
Let me repeat my idea again, lucky support it and Crystal support double splatting are totally two things.
To put it another way, if lucky not support use like this, how to solve my above issue when compiler complain double splatting a union namedTuple is not yet supported ?
It would be easier to bring support for this as its the better way to handle it. Double splatting gives you 0 benefit over just passing the collection type as is.
I edited my response once I realized it was a hypothetical question if Lucky didn’t support it.
EDIT: Tho I think to answer your question, as long as you ensure the value of each item in your named tuple is of the same type, String in this case, double splatting it should be fine. This is a reasonable requirement anyway as everything will be a string anyway.
The fact is, When I encountered this issue once or twice, I used the workaround i post in my post (jgaskins does same too), then I tried it, thanks lucky, it give me the option to pass a collection directly, that not have to force me to use that awkward workaround.