Ruminations of a Reflective Robespierre


OOPSLA '90 Workshop


Reflection and Metalevel Architectures

Brian Foote

18 October 1990

Mamdouh Ibrahim chair, Brian Foote, Jean-Pierre Briot, Gregor Kiczales, Satoshi Matsuoka, and Takuo Watanabe, organizers


The Ramifications of a Reflective


Object-oriented programming systems and languages are every bit as appropriate a domain for object-oriented programming techniques as are window systems, databases and the like...


Reflective and object-oriented approaches together, for the first time, provide us with sufficient power to allow a language to serve as the vehicle for its own incremental evolution


Reflective object-oriented architecures allow metalevel functionality to be distributed across a constellation of different metaobjects


Reflection allows the venerable vision of allowing one's programming system to encroach upon and supplcant large sections of the operating system and the user interface to be realized


An aggressively animistic perspective in which obects are tangible, active, first class entities that may dynamically alter their structures and their relationships with other elements of the environment in which they reside

Reflective Approaches have implications for:

programming language design

compiler construction

code generation

language design

programming environments

debugging, tracing

...even operating systems


(as per Tesler)

computation theory


Reflection affects how we think about translation


Polymorphism raises the level of abstraction of object-oriented code


More mechanics are subsumed into the metalevel

Hence, metalevel manipulation can have a greater impact


Reflection can tear down the distinctions between statically compiled and dynamically interpreted translation

(incremental compilation always seemed like a reasonable middle ground anyway...)

static vs. dynamic

batch vs. interactive


Reflection can influence the architecture of systems that embody the results of well-researched areas such as lexical and semantic analysis...

Possible Metalevel Components

(Potential Metaobjects)

(Things one might reify)

A Metaobject Pallette


In no particular order...


Selectors/Generic Functions/Keys/Operators



Method Dictionaries/Script/Scripts Sets/Role/Containers/Behaviors






Contexts (Method, Block)

Mailboxes/Message Queues

State Memory/Stores/Storage







Methods (Primitive and otherwise)

Code/Expressions/Parse Trees/Byte Codes/Forms



...and last but not least:




(other primitive objects)

Some meta-metalevel design issues:


Distributed (implicit) representation


Localized (explict) representation


Issues in consistency mainentance:

Everyone's favorite implementation strategy (at least at PARC, perhaps)

The single principle that underlies the results reported here is


Later they speak of "Multiple Rpresentation"


causal connection

dynamic structure

active structure

active representation

...even dynamic constraint maintenance/satisfaction


How might representation changes be instigated:


Uniform (Normal) representation: never

Equivalent representaion: implicitly (transparently, like PS contexts)

Convertable representation: explicitly (under user control)


Transparency vs. Convertability

Design Principles


Message Passing at the Bottom

all computation shall be conducted via message passing


Object-Oriented Uniformity

everything shall be an object

(including variables, "code", contexts, oops?)


Malleable Self-Representation

computations shall be represented by first class objects

at a semanticallly interesting level



behavior only shall determine an object's identity

(The Duck Test)


Inheritance is signature composition

at least from an extensional standpoint


State and Behavior

shall be externally indistinguishable

(state is, of course, architecturally significant

at certain levels)


Active Dispatching vs. Passive Lookup

shall be externally indistinguishable


Dynamic vs. Static Scope

(Operational vs. Denotational Scope)

static scope shall be dynamically implemented

(as it usually is, anyway)

Language Design:

The Hamiltionian Tradition


The Jeffersonian Ideal


The Hamiltionian tradition can be characterized by the image of the language designer as a sage locked in a castle in the Alps forever defining just what a language shall and shall not be able to do...

A favorite example: Pascal's utterly inflexible arrays


Reflection potentially puts this power in the hands of each and every user of a language


Metaprogramming: It's not for everyone

Of course, it is expected that most users will not need to resort to designing and building, as opposed to using, reflective facilities

Metaprogramming should not be undertaken frivolously

They should be there when they are needed.

A language should not be an

obstacle to its users, or to its own evolution

Metaprogrammers are a peculiar, but distinctive breed


The alternative: A sort of Software Stalinism

Monism vs. Dualism

and Metamorphosis


The question: do we effect dynamic structural alterations by manipulating

heavyweight objects


lightweight classes?


The perspective of an object is a discrete entity that is itself the captain of its own ship is useful at times

The perspective of an objects as being a member of a perhaps dynamic coalition that defines its behavior us useful as well...

Table I

1. Monitors

2. Encapsulators

3. Message Forwarding

4. Property List Manipulations

5. Accessible Objects (Dicts=Records=Props)

6. Multiple Views (Database style)

7. Capabilities (Access Control)/OS Style Protection

8. Multiple Inheritance

9. Tracing

10. Debugging (Many Mentions)

11. Futures

12. Remote (Distributed) Objects

13. Multitasking (transparent, perhaps)

14. Constraints

15. Reflection

16. Part/Whole Relationships

17. Active Values
Active Variables
Active Messages
Active References

18. "Smart" Variables

19. Lightweight (Anonymous) Classes

20. Melds (Garlan & Kaiser)

21. Actors/Daemons

22. Lazy Evaluation

23. Caching Schemes

24. Memo Memory Functions (as in POP2 and friends)

25. Read-Only Variables

26. Logging

27. Metering/Statistics/Performance Data Collection

28. Component Delegation

29. Atomic Objects/Actions

30. Protocol Translators/Adaptors

31. Open Systems (Protocol Negotiators?)

32. Multiple Inheritance Schemes

33. Delegated Inheritance (and other forms of sharing)

34. Multimethods (and other generic dispatch schemes)

35. Method Combination/Composition

36. Prototypes (ala Borning)

37. Modules (ala Wirfs-Brock)

38. Continuations? Catch/Throw?

39. Exception Handling of various sorts...

40. Dynamic Behavior Changes

41. Dynamic Class Changes

42. Dynamic Class Construction

43. "Smart" Paths (see Part/Whole)

44. Flavors (now CLOS)-Style Method Combination

45. Two Way Implicit Group Membership (like Part/Whole?)
(Perhaps encompassing the idea of "Enrollment"

(Randall Smith))

46. Implicit Coercion Schemes

47. X-Style Substructure Redirection

48. Event Dispatching (see Multimethods)

49. Alternate Memory Allocation Schemes

50. Multilevel (Virtual, in the OS sense) Object Allocation

51. Sundry Dynamic and Other Optimizations (Cointe)

52. Escape Operators (see Continuations) (B. C. Smith)

53. "Deviant" Variable Passing Protocols (B. C. Smith)

54. Planning/Supervisory Code (Genesereth, others)

55. Behavior Based Programming

56. Active Types

57. Strategy Computation

58. Truth Maintenance

59. Program Supervision

60. Multiprocessor Load Balancing

61. Active Values/Access Oriented Programming

62. Self Analysis (Code Walking)

63. Self description of a program's operational semantics

64. Smart Comments

65. Logic Variables/Unification

66. Agents

67. Virtual Time (Time Warp)

68. Version Management

69. Garbage Collection

70. Persistent Objects

71. Active Protocols

72. Algorithm animation

73. Language Level Viruses

74. Program Transformation




Reflective extensions to an objec t-oriented language should be as much built into the existing language as on top of it


In order to be practical, reflective facilities must be efficient


Some Strategies


Integrate these approaches into the Typed Smalltalk runtime environment or a custom runtime environment


Typed Smalltalk Types

Deutcsh and Schiffman Caches and Dynamic Changes of Representation (The PARC Strategy)

MMU stunts

Ungar's Customization/splitting


For instance, Method Lookup can be addressed as per

Foote and Johnson 1989

An appropriate self representation can permit implementation specific information to be attached to the linguisti structures that implement user defined reflective entities

Thus, user defined entities can affect their implementations

The Issues


Is this even possible?

Or are practical obstacles overwhelming?


Is it practical?

Can it be done efficiently?

Is it useful enough to worth doing?


What are the tradeoffs?

What do we include? exclude?


Do we have any other choice?

Brian Foote
Last Modified: 12 November 2005