Example code:
macro key_gen(name)
"{{name.id}}_id"
end
CHAT = "chat"
k1 = key_gen(name: {{ CHAT }})
k2 = key_gen({{ CHAT }})
puts k1 # => {{ CHAT }}_id
puts k2 # => chat_id
How do I pass a constant when I call it in the first way?
Example code:
macro key_gen(name)
"{{name.id}}_id"
end
CHAT = "chat"
k1 = key_gen(name: {{ CHAT }})
k2 = key_gen({{ CHAT }})
puts k1 # => {{ CHAT }}_id
puts k2 # => chat_id
How do I pass a constant when I call it in the first way?
I think I added that special rule to the compiler at some point, before we had named arguments… or maybe I didn’t take named arguments into account. I don’t know whether it was a good idea. But please open an issue in our main GitHub repository. Thank you!
I remember there are a LOT of unimplemeted macro expansion like that, @asterite you mentioned it while fixing one in a literal a (long?) time ago… Would be nice to implement more cases!
I think we should revert the current behavior. If you really want the value behind the constant you can call resolve
on the macro side.
How would that fix anything? I think you misunderstand the issue here, the problem is not the constant, it’s the MacroExpression
that is not expanded (https://play.crystal-lang.org/#/r/7a4g)
An alternative is to put that entire call inside a begin macro section. What I mean is that resolving macro expressions at that point is not intuitive or uniform.
What I mean is, we introduced this feature so we can do:
require "json"
require "yaml"
class Foo
MAPPING = {x: Int32, y: Int32}
JSON.mapping({{MAPPING}})
YAML.mapping({{MAPPING}})
end
That is, being able to reuse a mapping. However, this can also be done like this:
require "json"
require "yaml"
class Foo
MAPPING = {x: Int32, y: Int32}
{% begin %}
JSON.mapping({{MAPPING}})
YAML.mapping({{MAPPING}})
{% end %}
end
which doesn’t need this extra feature.
Additionally, we now have JSON::Serializable
and YAML::Serializable
which means the above can be written like this:
require "json"
require "yaml"
class Foo
include JSON::Serializable
include YAML::Serializable
property x : Int32
property y : Int32
end
so there’s even less need for this kind of macro magic.
That’s why I’m proposing reverting this “feature” when moving forward with the language. It simplifies the language (removes an extra strange rule).