I have a hash which stores a few different object types but with the way the application is structured, given a key it will always return a certain object type. That key may be missing through. I want to wrap it with accessors that simplify that type juggling.
Here is my macro:
private macro section_getter(name, type=String)
def {{name.id}}
ret = @data[{{name.stringify.capitalize}}]?.try &.as {{type}}
{% if type.stringify.starts_with? "Array" %}
ret ||= [] of {{type.type_vars.first}}
{% end %}
ret
end
end
The idea is to call it with something like:
section_getter foo
section_getter bar, Array(Item)
section_getter baz
The idea here is that if I call the foo
method I get back either a String
or nil
. Same with baz
. But bar
is different. It always returns an array although it might be an empty array. Basically if type is not an array then the method return an object of that type or nil. If the type is an array then it always returns an array but that array may be empty if the underlying hash didn’t have that key.
What I don’t really love is the if statement in the macro. I feel like I should have:
{% if type.is_a? Array %}
But that doesn’t work. I’ve tried various other things and none of them work so my hacky convert it to a string and see if it starts with Array
is the best I can do. It works but it seems like there should be a better way.