Jupiter_gh wrote:What I see to it, is that this strong coupling between objects and references should be loosened a little, meaning that references should be declared independently, and they serve as formal means in concept-oriented languages to specify address spaces. When comparing with object-oriented languages, references correspond directly to proxies. This means that a reference should declare the interfaces it "proxies". Objects are declared to be identified by one or more references. In other words, they are declared to exist in one or more address spaces. And thus, they should implement the interfaces "proxied" by the identifying references. In short, a concept-oriented language would have three equally modeled elements: Interfaces, Objects and References.
The initial version which is about 3-4 years old was very similar to what you describe. One of the main design goals initially was modelling address
spaces (environments) via references with arbitrary structure and functions. So concept as a language construct was defined as a reference class (without object class). Concept inheritance allowed us to model nested spaces where elements are identified via multi-segment references. So in that old version references were decoupled from objects and we could define separately structure/behaviour of spaces and that of objects.
Then the question was how we can specify the address space for each concrete object. For this purpose inclusion relation was used, i.e., there was inheritance for building hierarchy of references and objects (separately) and inclusion for specifying reference type for each object type. For example, if we want to represent objects of class Account by references of class Remote then we make the following declaration: class Account
in Remote. As far as I understand it is precisely what you mean when you say that "Objects are declared to be identified by one or more references" and "they are declared to exist in one or more address spaces".
In this approach, we had two kinds of classes and two kinds of relations and it looked relatively complex. After numerous attempts to reduce complexity and thorough analysis we came to a rather general conclusion that references cannot be modelled without objects and vice versa. In other words, we gradually came to understanding that reference and object are two sides of one thing and hence they should be modelled together. After that the main language construct was defined as a
pair of two classes.
Of course, there are many examples where references are quite independent of objects they represent. And there are even more examples where objects are completely independent of their references (the whole OOP, actually). However, concept as a pair of two classes does not prevent us from focusing on only one side (reference or object) or even completely ignoring the other side.
If references and objects are used separately as you describe then we loose the fundamental assumption about their inseparable unity. In this case we need to model their connection manually using common interfaces or other means/patterns. Then references will play a role of proxies with all the consequences.
Jupiter_gh wrote:When constructing objects, one may specify one or more addresses for this object. But at least one address should be specified at construction-time. Even more, it can be assigned a new address later (in other address spaces). What do you think?!
There are two design alternatives about address assignment:
- [Static] At class definition time. In this case we specify type of the address for the whole object class and hence all instances of this class will be automatically assigned some address at run-time. When a new variable of this class is declared we do not need to specify its reference type. For example: class Account in Remote { ... }.
- [Dynamic] At variable declaration time. In this case each new variable needs to have two parameters: normal class name and additional reference type. Thus instances of one object class can be represented by different references. This approach is used, for example, by smart pointers in C++. For example, Account in Remote myVariable = new Account();
Currently, CoP follows the first approach, i.e., we bind references and objects at the time of concept definition. It can be viewed somewhat restricted because we cannot change the type of references at run-time however it is quite consistent because it does not claim that it can do more. In other words, in the current version of CoP we can model the structure of address space only statically.
The second approach is highly interesting and I have been thinking about possible mechanisms to allow for dynamic assignment of references but unfortunately I do not have a consistent solution for that case. (Of course, it is always possible just to add a new dedicated mechanism but the goal is to add new functions without adding significant complexity.) This is quite useful feature. For example, it would allow us to create one bank account object in different containers depending on our current needs. For example, one account object could be created as remote object (if it is supposed to be passed to some remote computer for further processing) while the second object could be created in local fast buffer (if it is needed for temporary purposes in the scope of this method only). I see some possible solutions but they are not complete and will definitely entail considerable changes in the whole approach by introducing new or generalizing existing principles (like the nature of computations etc.) So it is again more about future...