Named arguments in macros with symbolized strings

We have an issue in Lucky where a user tried to pass Vue-specific html attributes using the crystal DSL. Unable to use specific VueJS attribute in Shared::Field · Issue #1409 · luckyframework/lucky · GitHub

In Lucky, it would work fine in normal circumstances:

button "Click Me!", "@click": "doThing()" #=> <button @click="doThing()">Click Me!</button>

but we have a certain scenario where we use the method_missing macro to decorate the html call and pass it along. lucky/tag_defaults.cr at 42e9b7b43356b729bf2b055b3ee9af5f2b92d768 · luckyframework/lucky · GitHub

When the method_missing macro is invoked, it’s passed a Call object that has a named_args method. The named args each have name and value methods. I’m sure the value method in particular trips a lot of people up at first because it’s not the actual value, it’s the variable name that will return the value and that is where the problem is. When named arguments are passed usually, the name of the argument can be used directly to retrieve the value but not in the case of the above where the named argument is "@click". That all makes sense to me but the problem is that it is possible to use that named argument if the method uses a double splat and captures them into a named tuple which is what we are doing in the normal case.

Does anybody know of a way to get the named arguments from a macro Call object and to pass them along without having to use the value it gives?

Maybe this could be considered a bug?

Here’s an example of the issue Carcin
With the "@click" it tries looking for an instance variable.

This appears to be a bug in Crystal:

class Thing
  macro method_missing(call)
    "{{call.named_args}}"
  end
end

Thing.new.omg(foo: "bar") # "[foo: foo]"

Filed an issue for it NamedArgument.name == NamedArgument.value in method_missing · Issue #10381 · crystal-lang/crystal · GitHub

From the discord:

image

https://play.crystal-lang.org/#/r/adw6

Pretty sure this isn’t a bug, but more of a limitation.

That’s super confusing, because you can forward method calls with method_missing. If Crystal can forward arguments along, then something has access to the call’s arguments inside the macro, right?

1 Like

If I can call a method that has a double splat like html("@click": "doSomething()") I believe that the method_missing macro should be able to support that as well. As it stands right now, it can’t because you cannot access the value of the named arg nor can you convert the named args into a NamedTuple.

1 Like