Egg
Egg is a Smalltalk-like system with late-bound names for improved modularity. The main difference is that resolving names dynamically allows for features that are more difficult to implement in traditional Smalltalk-80 systems.
this is a work in progress documentation, the code in the repos might not yet match what is described hereby
1. Namespaces
A namespace is an object that maps symbols to objects. In the original ST-80, the only “namespace” was Smalltalk object, whereas in Egg different contexts use different namespaces, which allow for the coexistence of independent libraries without the names of one interfering with the names of the other.
2. Modules
A module is a conceptual unit that defines a namespace, a series of dependencies, imported names, classes with methods and extension methods. As names defined in a module do not interfere with names defined in other module, the symbols of each module’s namespace are more tightly coupled than in say Smalltalk dictionary. For that reason, and to simplify, Egg classes do not use class variables: i.e. instead of having a SecondsPerMinute in the Timestamp class, you have SecondsPerMinute in the Kernel::Time module.
1. Module Methods (WIP idea/proposal)
Egg allows modules to define a kind of extension methods. These methods are added to the method dictionary of the class being extended, but are bound to the module in which they are defined. The module methods are accessible only with special syntax, by code that previously imported the module of the module method.
For example, anObject js::asJson
sends asJson
to anObject
filtering lookup through js
module. anObject asJson
results in a
doesNotUnderstand
(unless asJson
was also defined in the class of anObject
).
Extensions methods could allow for some interesting features not available in ST-80.
In Egg, reflection could be implemented in terms of module methods. To access
the class of an object, you will need to import meta
module, and then
send anObject meta::class
.
aRemoteArray meta::class -> RemoteObject
aRemoteArray remote::class -> Array
As meta
is not just a symbol but actually a late-bound variable name, it is possible
to make the module itself be dynamic (for example, fetching the module that implements
class
from a factory:
module := factory metaModule. "will return some module object like 'meta' or 'remote'"
aRemoteArray module::class "will send class to the module variable"
This could be used to implement some form of safety: as reflection is accessible
through module methods, accessing metaobjects could be disabled by prohibiting
access to meta
module (and to unsafe modules that could leak metaobjects).
It can also be used to stratify runtime implementation level and application level:
anObject vm::isSmallInteger
works as a barrier that can be implemented differently by different virtual machine implementations.
However, mixing dynamic lookup and primitive-like behavior might not
work well (doesn’t vm
lookup cause an infinite recursion? should a JIT lookup vm
or isSmallInteger
statically? is vm::isSmallInteger
atomic in any sense?).