code:
macro foo(obj)
p {{ obj.type }}
end
record Book, name : String, price : Float32
book = Book.new("foo", 33)
foo book
output:
10 | foo book
^---
Error: undefined macro method 'Var#type'
code:
macro foo(obj)
p {{ obj.type }}
end
record Book, name : String, price : Float32
book = Book.new("foo", 33)
foo book
output:
10 | foo book
^---
Error: undefined macro method 'Var#type'
The macro only knows it was given a variable, there isn’t a way to figure out the type of it at compile time given book
is a runtime thing. Going to have to provide it manually as a second argument, or try and figure something else out.
Crystal isn’t the static type? The type of var should be inferenced in compile-time
You can use a normal def with a free variable:
def foo(obj : T) forall T
{% p T %} # okay
p T # okay
end
Value type will cause copy , so macro must be used in some scenarios
Does it matter? Book
is so small in this scenario that it shouldn’t.
Do you even need compile-time access to the variable’s type? Does book.class
or typeof(book)
not work for your use case?
for example:
def get_instance_pointer(t : T) : Pointer(T) forall T
{% begin %}
{% if T.struct? %}
pointerof(t)
{% elsif T.class? %}
t.as(Pointer(T))
{% else %}
raise "{{T}} is neither struct nor class"
{% end %}
{% end %}
end
Do you realize that pointerof(t)
is only valid within the method to which t
is an argument?
If you leak that pointer outside the method, it will be broken because t
on the stack is out of scope.
yes, so my question is How to get type of var in macro
You still don’t need to get the type in this case, because only runtime checks are needed, not compile-time checks:
macro get_instance_pointer(t)
{% raise "`t` must be a Var, not #{t.class_name}" unless t.is_a?(Var) %}
{{ t }}.is_a?(Reference) ? {{ t }}.as(Pointer(T)) : pointerof({{ t }})
end
But note that t.as(Pointer(T))
is simply invalid as that effectively introduces an additional level of indirection. I am not sure what get_instance_pointer
is supposed to achieve.
I just want to give an example to explain that if you can get variable types in the macro, you can do more ;-)
Thank you for your patience anyway