How can I have pointer of trait object like rust ? #3169
-
Hi, I have a question abound For example, I have a
then I can use I search the document of mojo, but only found doc of Is the dynamic dispatch available now, or is it in plan ? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 7 replies
-
Hi, I just found a way to achieve dynamic dispatch in mojo. The main idea is to combine the Variant and trait in Mojo. With just a little runtime overhead, the performance should be very good. I have put the code on my github: https://github.com/liuzhishan/mojo-dynamic-dispatch. ImplementionA Variant is a sum type, such as enum in rust, or tagged union in c++ (or std::variant in c++17). It can hold a value that could take on several different, but fixed types. We can define several struct implementing one same trait, such as Echoable. And define a Variant from all these types, which is constrained by one same trait. Then we implement the trait Echoable for the Variant. For example: struct MyVariant[*Ts: Echoable](
Echoable,
):
...
fn echo(self) -> String:
var res: String = String("")
var cur = self._get_state()[]
@parameter
fn each[i: Int]():
if cur == i:
alias T = Ts[i]
res = self[T].echo()
unroll[each, len(VariadicList(Ts))]()
return res As the above code shows, when we have a Variant at runtime, we known its underlying type. We can compare it with all the candidate types, and then get the actual object, call the trait function. This has exactly the same effect of dynamic dispatch in rust or c++. The comparing between types is actually comparing using an int8, which is determined by the order of types in compile time. And loop of the types is unrolled in compile time using @parameter meta programming. At runtime, there are just some int8 comparing to determine which object to use. Only Exactly one of them will be true. I'm not sure how fast it is comparing to v-table in c++ or rust, but it should be really fast with only some int8 comparing. Wow, awesome mojo! We just implement dynamic dispatch in a library, not in the compiler! Just as mojo's design principle said, implement the language in library, not in compiler. Right now we cannot use trait as generic parameters. So Variant cannot be reused directly. Most of code are same as implementation in mojo UsageYou can use the same idea to implement your dynamic dispatch (like subtype in c++). For example: alias AOrB = MyVariant[A, B]
var a = A()
var b = B()
var x = AOrB(a)
var y = AOrB(b)
# result: this is A
print(x.echo())
# result: this is B
print(y.echo()) |
Beta Was this translation helpful? Give feedback.
-
Hi liuzhishan! P.S. on Discord, I am EzRyder (ezryder_ed, ID 771688661522841601) |
Beta Was this translation helpful? Give feedback.
Hi, I just found a way to achieve dynamic dispatch in mojo. The main idea is to combine the Variant and trait in Mojo. With just a little runtime overhead, the performance should be very good.
I have put the code on my github: https://github.com/liuzhishan/mojo-dynamic-dispatch.
Implemention
A Variant is a sum type, such as enum in rust, or tagged union in c++ (or std::variant in c++17). It can hold a value that could take on several different, but fixed types.
We can define several struct implementing one same trait, such as Echoable. And define a Variant from all these types, which is constrained by one same trait. Then we implement the trait Echoable for the Variant.
For example:
struct …