module Hierarchical
extend self
alias Types = Folder | Forum | Language | Manufacturer | Product | Topic | Page | Post
end
I would like to iterate through the types in a macro, so that I iterate upon Folder, Forum, …
I couldn’t quite figure out how to write that from the docs. It would be something like
{% for type in Hierarchical::Types.union_types %}
do_something_with( type.name )
{% end %}
but that’s not working. On the first iteration I get the name of the common superclass of all of my union types, with a “+” at the end.
The compiler merges unions of types that inherit from Superclass as Superclass+. This is typically useful to reduce the amount of overall types the compiler needs to keep track of when those unions just come together by chance (for example Folder.new || Forum.new).
abstract struct Foo
end
{% for type in %w[Folder Forum Language Manufacturer Product Topic Page Post] %}
struct {{type.id}} < Foo
end
{% end %}
module Hierarchical
extend self
alias Types = Folder | Forum | Language | Manufacturer | Product | Topic | Page | Post
end
{% for type in Hierarchical::Types.union_types %}
{% if type.subclasses.any? { |s| s } %}
{% for subtype in type.subclasses %}
{% pp subtype %}
{% end %}
{% else %}
{% pp type %}
{% end %}
{% end %}
It works with and without the inheritance, you’ll just need to make sure you do the same thing with subtype as with type if you want to support both, maybe by extracting the behavior to a macro.
This is an entirely different angle. Your example prints all subclasses of Foo, even those not included in Hierarchical::Types.
If you add struct Bar < Foo; end to the code, it get’s listed as members of Hierarchical::Type. This techincally correctly reflects how the compiler treats this union, but it probably doesn’t fit the intended use case of that union. If it did, there would be no reason to list the sublasses explicitly as union members, you could just use the superclass (either directly or as a union with non-inherited types).
A tuple that holds all the type classes can be used:
class A
end
class B < A
end
module Hierarchical
extend self
{% begin %}
{% types = %w(A B)%}
alias Types = {{types.join(" | ").id}}
TypesTuple = { {{types.join(", ")}} }
{% end %}
end
{% for type in Hierarchical::TypesTuple %}
puts {{type}}
{% end%}