Yes, CLOS has no methods. There is a pattern that fills the same purpose as constructors. But there are only functions. It might help to understand ancient history.
Classes were just lists with a fixed structure. All instance of the class the same set of lists, with different CDR.* Classes normally used the same (eq) lists unless the element was different than the class definition. Instances just had an eq link to the class object at the top of the list structure. A constant reference for every instance. Classes had a List of types/classes/mix-ins at the same place. There is very little difference between a class and an instance. When the instance had many of default instance it used the class’s list structure.
Anonymous super/mix-in classes are possible. As everything is a list, the links have a guaranteed linearity. The class itself is a type. -T are no different than +T.
Structural inheritance is having the same list structure(s).
Functions are a list. There really isn’t a difference between a data list and a function list. The functions are just executed rather than data.
By the time of The Little Lisper with objects added, functions could be affected by the make-specializable function. That changed the definition of the function. The function would execute the type (named or anonymous) specific function based on it’s parameter’s type.
Modern CLOS systems have optimized the entire implementation, not everything is as simple as the Little Lisper interpreter. Think of it as Hotspot for classes & instances along with functions.
Classes can have +T or -T or more complex composition. The class definition is static, structural. Functions are pattern matched/specialized based on a class. The class itself may be anonymous. In all cases, the classes are pre-linearized. The function is specialized. The class itself doesn’t own the function. The function controls its own specialization. Call-next is owned by the function.
The closest thing to methods are just functions that expect the class to be part of the parameter. In this, one doesn’t know details about the implementation of the classes and other functions. One know and can depend on the semantics of the other functions. In Java, the need is caused by needing the implementation, but not knowing the implementation.
In a proper type system, +T and -T calculus can not be guaranteed to halt. In CLOS, the operations are on physical data structures. In that, -T isn’t really supported. [or wasn’t, things might have changed]. The result of type calculus is really applying a function on the type representation. It’s possible to construct a function that doesn’t halt, in practice it’s not possible to create a function given the combination rules.
It is more possible that the function create a pattern match that doesn’t halt. In general, the developer’s mind will implode before that kind of pattern matching problem will blow up the compiler or run-time system.
To make it short
- There are only functions
- Constructors are functions that manipulate the creation of the data structure of an instance.
- Structural inheritance is owned by the class.
- Function pattern matching is owned by the function itself. Both the function and the class matched may be anonymous.
- -T will destroy the developer’s mind before it will realistically destroy the compiler. The downside is -T isn’t really supported.
A) Changing the schematics of scala to hand the same general case would be very difficult and require a lot of hard analysis to define.
B) The primary need in scala is from needing the implementation’s behavior, but not having it.
C) Limiting it to the direct extends would require less thinking and much less implementation (I think).
- All lists were made of Tupple2. CDR being the ._2. CAR is ._1. Head/tail might make more sense to people.