I can easily convert a union type into an ArrayLiteral
. Is there also a way to do it the other way around?
I’d like to reduce a union type and make a new one out of it…
alias X = Int32|String|Nil
{% if true %}
{{ X.union_types.select {|el| el != Nil} }}
{{debug}}
{% end %}
I don’t think union types can be “dynamically” created, in the sense that the types are known but reducing the types to another type via the macro methods would count them as dynamically created.
You can actually do this by using the Union type directly. E.g.
alias X = Int32|String|Nil
{% if true %}
{% types = X.union_types.select {|el| el != Nil} %}
alias Y = {{"Union(#{types.join(",").id})".id}}
{{debug}} # => alias Y = Union(Int32, String)
{% end %}
y : Y = 1
pp y # => 1
2 Likes
I just realized it doesn’t help me (yet) completely…
The solution works for alias types (X
in example), but not for generic types (T
in example); is there a solution for this as well?
alias X = Int32|String|Nil
class C(T)
{{"alias U = Union(#{X.union_types.select {|el| el != Nil}.join(",").id})".id}} # X works, but T doesn't
def initialize
p U
end
end
C(X).new
That said, having a subtract operation in type algebra would be nice.
1 Like
It seems macros are rather restrictive:
alias X = Int32|String|Nil
class C(T)
{{"alias U = Union(#{X.union_types.select {|el| el != Nil}.join(",").id})".id}} # X works, but T doesn't
# @x : {{"Union(#{T.union_types.select {|el| el != Nil}.join(",").id})".id}} = 0 # doesn't work for neither X nor T
def initialize
p {{"Union(#{T.union_types.select {|el| el != Nil}.join(",").id})".id}} # both X and T work
# @x = 0.as({{"Union(#{T.union_types.select {|el| el != Nil}.join(",").id})".id}}) # doesn't work for neither X nor T
# @x = 0.as(Int32|String) # works
end
end
C(X).new
In particular:
- the locations where macro substitutions
{{...}}
can be put are restricted (e.g. not where types are expected, after double colon or with #as
- generic type usage is working only inside methods
Which makes me wonder since I now learned we can put almost all code in macros this way: {{"p 42; p 12".id}}