A Metaobject Protocol for C++ (1995) [pdf]
dl.acm.org
dl.acm.org
One of the use cases for metaobject protocols was to make distributed objects look like normal objects by declaring them as such. You could write C++ classes and then annotate them (in the metadata layer) as distributed, and suddenly you had distribution transparency. Except, distribution transparency turned out not to be a good thing as it is a leaky abstraction. See the 10 fallacies of distributed systems for why this is so. EJB also killed the use case, as it was actually a solution for it. It did build on some principles from this research - enable pre- and post-method invocations to be pushed to application deployment time. EJB enabled methods to be "transactional" or "filtered" and so on. Aspect-oriented programming was a rebranding of metaobject protocols that also didn't have huge impact. As for me, i finished my PhD in the field and moved on to other research.
In 1995 most computers had a single CPU core, running at around 100mhz. Today each core is 10-30x higher frequency (though as always you cannot compare frequency directly it is still a sign of relative speed), and almost all computers have at least 4 cores. In 1995 you were doing good to get 8 MB of RAM, now we are looking at around 8GB. One way around the inherent slowness of computers is another one on the network to run some programs.
In 1995 there were cool demonstrations where a program could plugin others for some functions. So your word processor wouldn't have a spellcheck, it would just use a third party spell check of your choice. (we sort of do that with shared libraries, but the interface is different) Some of what was done then was better than anything we have today (but see the other replies, making distributed work transparently is not easy and so if we had made it work people would probably hate how often it failed)
(I know I could google all this. It’s more fun to chat about it.)
The architects of these systems definitely took inspiration from these meta-object protocol papers and related LISP and Smalltalk efforts. Nobody quite took it all the way, and I suspect that's because the boundaries between compile-time reflection, use site checked macro programming, and declaration site checked type level programming are quite hard to pin down in such a general system.
Unfortunately to this day, COM tooling remains quite clunky, despite how much WinDev pushes it since Windows Vista as main API ABI.
https://herbsutter.com/2017/07/26/metaclasses-thoughts-on-ge...
This paper proposes a new MOP for C++, called OpenC++ Version 2. Like previous MOPS, it allows programmers to implement customized language extensions such as persistent or distributed objects, or customized compiler optimizations such as inlining of matrix arithmetic. These can be implemented as libraries ’ and then used repeatedly. Unlike previous MOPS, our proposal incurs zero runtime speed or space overhead compared to ordinary C++.
To make this possible, our MOP works by providing control over the compilation of programs rather than over the runtime environment in which they execute.
Chiba worked with folks at PARC, and this is a year after Gregor Kiczales wrote the book, The Art of the Metaobject Protocol. Kiczales designed AspectJ, still in use in Spring today.
The three design dimensions for metaprogramming are static vs dynamic, whole-program vs incremental, and raw vs typed.
AspectJ committed to incremental (and removed whole-program features like callee-side call join points) because Eclipse's incremental compilation made enterprise programming bearable (and of course Java chose it for loading classes).
Staticly, AspectJ did reduce the pointcut shadow at compile-time (unlike (remote) method interception which), but semantically still supported type-safe dynamic checks (mainly instance-of and limited control-flow via a thread-local).
But types were the best part: unlike reflection-based proxies in Java (that formed the basis for most of the EJB/Web containers), AspectJ advice could be written to expose only the required context, and only in a type-safe manner. Inter-type declarations were guaranteed valid at compile-time (and supported default methods 20 years before Java did). And most importantly, the code with aspects was binary- and source-compatible with any code using the unmodified code.
(Of course, it also helped that Java supported debugging from extrinsic source files for JSP's, so you could step into aspects as you like.)
AspectJ static and incremental made it usable, but typed made it safe and correct and understandable.
(And btw, Kiczales dropped out of MIT.)
https://github.com/steinarb/interviews
original paper describing it here:
http://i.stanford.edu/pub/cstr/reports/csl/tr/88/358/CSL-TR-...
Which in turn begat "Fresco" which then there was an attempt at a successor called "Berlin" by Graydon Hoare (of Rust fame), but it was, I believe never finished. I remember following it eagerly.
Everything was a hodgepodge.
Bad memories.
However things eventually moved on, when I started using GNU/Linux in production, it was either Tcl/Tk or Swing.
[1] https://www.softwarepreservation.org/projects/c_plus_plus/li...
Here’s a copy of the manual: https://bs2manuals.ts.fujitsu.com/download/manual/177
Thanks for sharing the manual.
Don't get me wrong, this isn't a terrible idea in that it does have some use cases. But also, I wonder if the authors would be better off adding the MOP to a language like C which is simpler and would benefit more from having extra features.
CLOS does not use methods attached to classes, which can be invoked by message sending or similar. Instead CLOS uses Generic Functions which consist of one or more Methods. Methods are dispatched over classes, using possibly multiple arguments. Generic Functions are themselves objects and they are defined outside of classes. When a Generic Function gets called, all the applicable Methods are combined to an Effective Method that then will be executed.
- you can send it to another machine turning it into RPC, and you can encrypt (some of) the parameters because of this
- you can add save the program state before you execute it for checkpointing purposes
- you can log the parameters for tracing
- ...Just because some language does not have classes doesn't mean you cannot implement a functional substitute.