-
Notifications
You must be signed in to change notification settings - Fork 50
Generics
Below myfunc
is defined twice, in each definition x
is given a different type, int
and string
.
def myfunc( x:int ):
print( x * 100 )
def myfunc( x:string ):
print( x + 'world' )
Now myfunc
can be called with an int or string type.
def main():
myfunc( 10 )
myfunc( 'hello' )
https://github.com/rusthon/Rusthon/blob/master/regtests/c%2B%2B/generics.py
Manually redefining the function for each type of argument type combination quickly becomes tedious, like above. As a special case for dealing with sub-classes that share a common base class, Rusthon will regenerate the function for you with each possible combination of the sub-classes for the function arguments. This requires that methods and data members accessed inside the function body all conform to the same type interface.
class A:
def __init__(self, x:int): self.x = x
def method1(self) -> int: return self.x
class B(A):
def method1(self) ->int: return self.x * 2
class C(A):
def method1(self) ->int: return self.x + 200
Here is how to manually define a generic function my_generic
that takes any type of A
:
def my_generic( g:A ) ->int:
return g.method1()
def my_generic( g:B ) ->int:
return g.method1()
def my_generic( g:C ) ->int:
return g.method1()
Above is the C++ style of doing generics, but it is not very pythonic.
In this case where the function body is the same for each argument type,
it is better to let Rusthon generate the extra functions, by giving the base class A
as the type for g
, the translator will know to regenerate the function for each subclass of A
def my_generic( g:A ) ->int:
return g.method1()
Above is translated into 3 my_generic
functions in c++, where g
becomes: A
, B
, and C
c++ output
int my_generic(std::shared_ptr<A> g) {
return g->method1();
}
int my_generic(std::shared_ptr<C> g) {
return g->method1();
}
int my_generic(std::shared_ptr<B> g) {
return g->method1();
}
https://github.com/rusthon/Rusthon/blob/master/regtests/c%2B%2B/generics_subclasses.py
If your function takes multiple arguments that are subclasses, watch out, because this can lead to generating lots of code, because the translator generates each possible combination.
def my_generic2( g1:A, g2:A ) ->int:
return g1.method1() * g2.method1()
c++ output
int my_generic2(std::shared_ptr<A> g1, std::shared_ptr<A> g2) {
return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<C> g1, std::shared_ptr<C> g2) {
return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<B> g1, std::shared_ptr<B> g2) {
return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<B> g1, std::shared_ptr<C> g2) {
return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<B> g1, std::shared_ptr<A> g2) {
return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<C> g1, std::shared_ptr<A> g2) {
return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<A> g1, std::shared_ptr<C> g2) {
return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<C> g1, std::shared_ptr<B> g2) {
return (g1->method1() * g2->method1());
}
int my_generic2(std::shared_ptr<A> g1, std::shared_ptr<B> g2) {
return (g1->method1() * g2->method1());
}