Agents versus Adapters
This really applies to all incarnations in all languages of higher order functions in Object Oriented languages. At a high level, this article is a case for using adapter classes in place of agents.
Agents provide two main things, the ability to pass around a routine (higher order function) and the ability to fill in parameters at different points in execution (closure/continuation).
Agents as higher order functions: The functionality of agents as higher order functions is not orthogonal to other language constructs. The role of agents can simply be replaced with polymorphism and in fact, a polymorphic class better satisfies the role because contracts can be associated with a class, whereas they cannot be associated with an agent.
An agent of the form:
Agents as closures/continuations:
Using agents as closures and continuations is also not orthogonal with other language constructs. An ADT will satisfy this requirement:
Another consideration to take in to account is the extensibility of agents. It's one thing if you need a single higher order function but what if you need a grouping of functions to be passed around together, possibly with some ancillary data. With agents you might group them together in a TUPLE:
One definite difference between the agent and class implementations is the terseness of the agent implementation. There's a lot of boilerplate code that needs to be added to adapters in order to make them work when the agent syntax is so seductively simple. The terseness of creating an agent loses some ground against the verboseness of handling them and of course they are not as expressive as adapters.
As above, handling a complex container of agents might look like:
To make better use of adapters and help with boilerplate code, I would suggest an EiffelStudio tool that allows adapter class generation with the following method.
- Add an additional item to the "Refactoring" toolbar named "Generate Adapter".
- This button accepts a class stone of the deferred adapter class from which to generate a implementation.
- The dialog would then present a window listing classes in the system.
- Classes containing the necessary feature signatures to fully create an adapter would appear completely opaque while classes not containing the necessary features would appear partially translucent to indicate some features will need to be implemented manually.
- A group exists for each deferred function that needs to be implemented by the target class
- Each group would have a check box option to create closure setters, BOOLEANs, and contracts for the routine, and a selection box listing the possible routines to use to use with signatures matching the deferred feature.
- The tool would then generate the desired class.
Below is an embarrassingly simple and ugly example of the proposed tool's dialog window.