-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Auto dispatch create methods in python #5118
Conversation
MachineEvaluation, StructuredModel, FactorType, ParameterObserver, | ||
Distribution, GaussianProcess, Alphabet>; | ||
|
||
namespace types_detail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome!
class ShogunInterfaceToPyObject : public InterfaceTypeVisitor | ||
{ | ||
public: | ||
virtual void on(std::shared_ptr<SGObject>* v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor thing, but now we are trying to always use override
instead of overwriting virtual functions
virtual void on(std::shared_ptr<SGObject>* v) | |
void on(std::shared_ptr<SGObject>* v) override |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
override FTW
// to query the swig_type in run time and be less implementation dependent maybe? | ||
// but this is faster and should not cause problems | ||
#define SHOGUN_GET_SWIG_TYPE(name) \ | ||
SWIGTYPE_p_std__shared_ptrT_shogun__##name##_t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if this can be generalised to the other swig interfaces?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming you mean the whole file. I would guess so. factory_python
is a horrible name for that regard. Any name suggestions?
Edit: I will call it factory_visitors.i for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, that's fine. And yes, I meant if you could for example template ShogunInterfaceToPyObject
, and the template determines the interface object type, e.g. ShogunInterfaceFactory<PyObject>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have two reasons not to:
- Added complexity without any other use case at the moment.
- After reading "GetterVisitor" I don't see any place for this visitor in the future (and maybe not for InterfaceClassVisitor either). Once the parameter framework and AnyVisitor support base types we can get rid of both new visitors, and use GetterVisitor directly, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since R is working now, I should make this generic as you suggested :"D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, that would be great! Then it could be easier to add other languages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. This should work with octave as well.
nullptr, nullptr, SHOGUN_GET_SWIG_TYPE(SGObject), | ||
SWIG_POINTER_OWN); | ||
} | ||
return m_pyobj; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even if it should not be possible to reach this, could you replace this with an exception? The worst thing that can happen is segfault in Python, because then the interpreter crashes. An exception can at least be handled gracefully
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I return a python null object. I will change the function call to SWIG_Py_Void()
to be more clear and add a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scratch that. Throwing is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, agreed, throwing would provide more information. Getting None
from a factory might be odd for a user
I can see this visitor being integrated into the GetterVisitor (making AnyVisitor inherit from InterfaceTypeVisitor for example, and defaulting the new methods to |
Not yet, it's been worked on in #4793 |
virtual void on(std::shared_ptr<ParameterObserver>*) = 0; | ||
virtual void on(std::shared_ptr<Distribution>*) = 0; | ||
virtual void on(std::shared_ptr<GaussianProcess>*) = 0; | ||
virtual void on(std::shared_ptr<Alphabet>*) = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if there could be a way to automatically generate this? Then again the base types probably do not change that often
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do type erasure as follows
virtual void on(std::shared_ptr<void>*) = 0;
and then try to dynamic_cast
for all base types one by one (with generic for loop on types) and dispatch to a generic on
.
template <typename BaseClass>
void on(std::shared_ptr<BaseClass>*);
But this is slower.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can alaso manually construct the virtual table of on
methods using a polymorphic lambda. So we would have something like
// vtable is constructed from one polymorphic lambda
std::tuple<std::function<void(std::shared_ptr<BaseClasses>*)>...> vtable;
template <typename BaseClass>
void on(std::shared_ptr<BaseClass>* ptr)
{
std::get<TypeToIndex<BaseClass>::value>(this->vtable) (ptr);
}
This should be just as efficient as multiple virtual methods, but it requires complex code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the manual vtable is similar to what we have in Any and use in SGObject
shogun/src/shogun/base/SGObject.h
Line 768 in 9b8d856
void register_parameter_visitor() const |
I wonder if the same logic could be used. I guess it would only be possible if we add another base class between SGObject and the "base" classes, where it would register types to be used (somehow) in the interfaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type erasure solution is kind of what we have/had in SGObject but we are moving away from that and just use visitor patterns.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This issue is now being closed due to a lack of activity. Feel free to reopen it. |
This fixes #4998 using the same technique that @gf712 suggested. I created a visitor for interface classes and changed the
create
method inclass_list
to accept the visitor. Then used this visitor in swig to transform the interface object to PyObject.