
pon., 14 kwi 2025 o 22:44 Jean-Louis Leroy via Boost <boost@lists.boost.org> napisaĆ(a):
Before going over your remarks, a bit of context: OpenMethod is derived from YOMM2 (https://github.com/jll63/yomm2, started in 2017), which is a rewrite of YOMM11 (2013). I presented it at several conferences, the most prestigious being CppCon, in 2018. My most recent talk was at Core C++ in Israel, last year. The latest video of a talk is from using std::cpp in Madrid, here: https://youtu.be/cOYE6OiuuMo?si=wMsSADt3_sEC-qz1.
I know that YOMM2 has been used in production in several places (like the Tokyo Institute of Technology), by people who cared enough to send me PRs, bug reports and suggestions. Also, vanity Google searches turned up conversations with positive remarks on YOMM2, between people I never heard of.
Thank you. So I had a look at the YOMM2 documentation, and I must say I find the motivation in YOMM2 stronger. It mentions the "cross-cutting concern" and the to_json+Matrices example: they are concrete and practical. I think OpenMethod would benefit from taking the motivation section from YOMM2. I am not sure that I am convinced, even with YOMM2, but I am certainly more convinced.
[2]. The motivation
In C++ we already have a dynamic-dispatch tool for "closed set of methods with open set of types": virtual functions. We also have a dynamic-dispatch tool for "open set of methods with closed set of types": the visitation of std::variant.
Why can't we have both at the same time?
The very fact that we have those two tools proves that extensibility is desirable along both axes: behaviors and types. Currently there is no easy way to write a library that is extensible in both directions.
It is clear (to me) that we sometimes need extensibility along one axis, and sometimes along the other axis. It is not clear to me that we ever need extensibility along two axes at the same time. On the other hand, I can see how the extensibility along two axes is error-prone: there is no static checking anymore. There is no way for the author of one part of the app to convince themselves if they extended their part comprehensively, as they do not know what other parties are extending in other parts of the program.
I believe that tying polymorphism to membership was the main cause of the failure of the Simula/Smalltalk/C++ way of OOP. Lisp was right.
Even if this was true, this is not necessarily an argument in favour of open methods. You can also have a non-intrusive polymorphism on class hierarchies, as proposed in P2688R5 (pattern matching) and implemented in Mach7 (https://github.com/solodon4/Mach7).
You need to provide a motivating example (more convincing than the zoo) that needs exactly this: "open set of methods with the open set of types". The arithmetic expression example doesn't do the job: there is a fixed and well known list of concrete types.
The papers authored by Stroustrup and his PhD students Pirkelbauer and Solodkyy contain discussions of several examples. The most "recent" is N2216 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2216.pdf).
Question: do users need to read the above paper to appreciate the library and understand why they would need it?
I disagree about AST. The narrative is: I have that AST library. One of my apps needs to represent the AST in JSON. If I own the library, I can add a virtual function, but then all the other apps get it, need it or not. And also the function's dependencies, e.g. the iostream library if `to_json` writes to a `std::ostream`.
I should explain in the tutorial how open-methods can help with decoupling. It's not just about the Expression Problem. It's also about the banana-gorilla-jungle problem.
The "expression problem" looks like an academic problem, or a logical challenge, but not a practical problem. The authors of N2216 (open methods) then switched to N3449 (pattern matching), as a more practical and safer solution to the same problem: you get the non-intrusive polymorphism and a guaranteed static checking.
If AST is a 3rd party library, it might provide a Visitor, if I'm "lucky". But Visitor is so clumsy. See here https://github.com/jll63/Boost.OpenMethod/blob/master/examples/slides.cpp for implementations of `to_json` using type switches, function pointers, Visitor and open-methods. This talk is worth watching too: https://www.youtube.com/watch?v=QhJguzpZOrk .
If you are comparing open methods to a visitor pattern, then I agree that the latter is clumsy. But if we compare open methods to a "type switch" (pattern matching), the latter is cleaner and safer (as in: "buggy usages are detected at compile-time or clearly visible").
When a program starts running, the set of operations and types is usually fixed (barring dynamic loading). Many such programs still use virtual functions, for many good reasons. They don't exist in isolation; they are part of a collection of programs that use internal and 3rd party libraries. It's about architecture.
Ultimately, open-methods are a better version of virtual functions. More flexible, not toxic.
Again, I think you will need to convince us that open methods are preferable to a type-switch (pattern matching). Based on my current understanding, I am inclined to think that the OpenMethod library is offering a suboptimal solution to what I recognize as real life problems. Regards, &rzej;