DCI in native Javascript

154 views
Skip to first unread message

Matthew Browne

unread,
Jun 15, 2015, 12:58:44 PM6/15/15
to object-co...@googlegroups.com
Hi all,
I had an "aha" moment and realized that by using functions rather than objects to reference roles, it seems to be possible to implement DCI without sticky injection problems in native Javascript. Here's some example code:

function TransferMoney(source, destination, amount) {
    var bindRole = dci.bindRoleFn(roles());

    var Source = bindRole(source, 'Source'),
        Destination = bindRole(destination, 'Destination'),
        Amount = bindRole(amount, 'Amount');
        
    Source('transferOut');
    
    function roles() {
        return {
            Source: {
                transferOut: function() {
                    self('withdraw');
                    Destination('deposit');
                }
              , withdraw: function() {
                    self('decreaseBalance', Amount());
                }
            }
        
          , Destination: {
                deposit: function() {
                    Destination('increaseBalance', Amount());
                }
            }
        
          , Amount: {}
        };
    }
}

And a jsFiddle with the full code:

It would be ideal of course to call role methods using normal object syntax, but that doesn't seem like a big downside especially since it would be fairly trivial to support a nicer syntax and do a simple source transformation. Of course, if doing source transformation, there might not be any advantage of the above code over our usual injectionless technique. So I suppose the main benefit is that it works in native JS without the need for a compilation step (or compiling Context functions on the fly at run-time).

By the way, the use of source transformation has often been mentioned here as a downside, but I was thinking...if the code that gets output is very similar to the original source as it would be in this case, then when debugging all the line numbers would still be the same and only the column/character number would be off. Javascript has source maps, but even in languages without them, I wonder if we're making a big deal over something that really isn't that inconvenient.

A couple notes on the code...

The use of 'self' relies on a hack -- assigning a global 'self' variable -- but it works as long as there are no (asynchronous) callback functions inside the role method. If there are, there's a simple workaround if you still want to use 'self', e.g.:

var self = Source;
setTimeout(function() {
    self('withdraw');
}, 1000);

The other downside is that IDE support would be limited since role method names are passed as strings, but again, that could be made possible with some very simple source transformation (keeping all line numbers the same).

I also created a second version that is more injectionful, so we can compare them:

In that example, the role methods are added to a hidden __roleMethods property in the object. Here's the difference in how the role method is retrieved:

var method = roleMethods[roleName][methodName]; //injectionless
var method = player.__roleMethods[methodName]; //injectionful

The hidden __roleMethods property could be useful for reflection/debugging but I don't see the point in looking up the method on the object rather than looking it up from the role methods map belonging to the context. I just implemented it that way to show that it could be more fully injectionful. Next I'll be creating an injectionful version that allows for name conflicts between roles and contexts (which I realize is still a subject of debate); since the role methods are stored in a hidden property rather than being injected as top-level properties of the object, this should definitely be possible from a technical perspective.

I'm surprised I didn't think of using functions in this way before; it seems to work quite well...is there some major flaw I'm not seeing?

Thanks,
Matt

Egon Elbre

unread,
Jun 15, 2015, 2:14:39 PM6/15/15
to object-co...@googlegroups.com
Identity is broken, add document.write(Source === source) anywhere.

Matthew Browne

unread,
Jun 15, 2015, 2:21:34 PM6/15/15
to object-co...@googlegroups.com
You have to call the function in order for it to work. Source() === source returns true.

If you call Source() with no arguments, it returns the source object, or if you call it with arguments then the first argument is the name of the method (or property) and the remaining arguments (if any) get passed as arguments to the method.

It's unusual to have to put parentheses after every role identifier but does that make it an invalid DCI implementation? I don't think so...if so, why?

Thanks,
Matt

Egon Elbre

unread,
Jun 15, 2015, 2:37:36 PM6/15/15
to object-co...@googlegroups.com


On Monday, June 15, 2015, Matthew Browne <mbro...@gmail.com> wrote:
You have to call the function in order for it to work. Source() === source returns true.

If you call Source() with no arguments, it returns the source object, or if you call it with arguments then the first argument is the name of the method (or property) and the remaining arguments (if any) get passed as arguments to the method.

It's unusual to have to put parentheses after every role identifier but does that make it an invalid DCI implementation? I don't think so...if so, why?


By the same argument why wrapper is an invalid DCI implementation. This implementation is just a wrapper in disugise. In this case the wrapper is a function instead of an object.

+ Egon

Matthew Browne

unread,
Jun 15, 2015, 3:54:36 PM6/15/15
to object-co...@googlegroups.com
I don't think it's the same as a wrapper implementation. It's always the same object, you just have to put in some parentheses to get to it...the only wrapper object the programmer has access to is the "role function" itself, and it doesn't do the programmer any good to use that directly because no methods can be called on it directly. It would also be possible to forbid incorrect usage...it should use a smarter regex or a real parser, but here's an example to show the idea:

var ctxSrc = ctxFn.toString();
var methods, rexp;
for (var rName in roleMethods) {
    methods = roleMethods[roleName];
    rexp = new RegExp('\\s' + roleName + '(?!(\\s*\[\(=:]))', 'g');
    for (var methodName in methods) {
        //TODO use a better regex than this naiive one
        if (rexp.test(ctxSrc)) {
            throw new Error("Syntax error: In this DCI implementation, roles must be called as functions, e.g. MyRole('foo') instead of MyRole.foo()");
        }
    }
}


Fiddle: http://jsfiddle.net/mbrowne/bjtexdb8/3/

BTW, I suppose you consider that Trygve's Java\UC implementation uses wrappers in disguise also?

Matthew Browne

unread,
Jun 15, 2015, 4:23:36 PM6/15/15
to object-co...@googlegroups.com
There was a small error in the wording of the error message that gets thrown when attempting to call a non-existent method. The error should have been:

throw new Error("The method '" + methodName + "' does not exist on this object of type '"
                        + player.constructor.name + "' nor on the role '" + roleName + "'");


...since the called method could indeed exist on a role other than the one that was called. (The original error message said "nor on any of the roles it is currently playing".)

Egon Elbre

unread,
Jun 15, 2015, 5:58:08 PM6/15/15
to object-co...@googlegroups.com


On Monday, June 15, 2015, Matthew Browne <mbro...@gmail.com> wrote:
On 6/15/15 2:37 PM, Egon Elbre wrote:
On Monday, June 15, 2015, Matthew Browne <mbro...@gmail.com> wrote:
You have to call the function in order for it to work. Source() === source returns true.

If you call Source() with no arguments, it returns the source object, or if you call it with arguments then the first argument is the name of the method (or property) and the remaining arguments (if any) get passed as arguments to the method.

It's unusual to have to put parentheses after every role identifier but does that make it an invalid DCI implementation? I don't think so...if so, why?


By the same argument why wrapper is an invalid DCI implementation. This implementation is just a wrapper in disugise. In this case the wrapper is a function instead of an object.
I don't think it's the same as a wrapper implementation.

I agree that it's not exactly the same. Something between name mangling and wrapper is more appropriate.

But just because you make impossible to access the wrapper, doesn't mean it's not there. But I agree that it's safer than an accessible wrapper. It feels like something that can break under some circumstances, e.g. eval("Sou" + "rce"). Than again I can't think of a real world case where this could happen.

There's also the same problem Java/UC had, i.e. the clarity of code is affected due to the parens, although less than in Java/UC.

 
It's always the same object, you just have to put in some parentheses to get to it...the only wrapper object the programmer has access to is the "role function" itself, and it doesn't do the programmer any good to use that directly because no methods can be called on it directly. It would also be possible to forbid incorrect usage...it should use a smarter regex or a real parser, but here's an example to show the idea:

var ctxSrc = ctxFn.toString();
var methods, rexp;
for (var rName in roleMethods) {
    methods = roleMethods[roleName];
    rexp = new RegExp('\\s' + roleName + '(?!(\\s*\[\(=:]))', 'g');
    for (var methodName in methods) {
        //TODO use a better regex than this naiive one
        if (rexp.test(ctxSrc)) {
            throw new Error("Syntax error: In this DCI implementation, roles must be called as functions, e.g. MyRole('foo') instead of MyRole.foo()");
        }
    }
}


Fiddle: http://jsfiddle.net/mbrowne/bjtexdb8/3/

BTW, I suppose you consider that Trygve's Java\UC implementation uses wrappers in disguise also?

I don't have the code at hand, and tablet doesn't want to open the file, but as I recall it's more of a manual name mangling rather than a wrapper.

--
You received this message because you are subscribed to a topic in the Google Groups "object-composition" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/object-composition/nnxDYYMC5qc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

Matthew Browne

unread,
Jun 15, 2015, 6:06:42 PM6/15/15
to object-co...@googlegroups.com
Thanks for the feedback. I think I may be on to something here...

Here's a working port of your Dijkstra implementation:
http://jsfiddle.net/mbrowne/8hw0at7r/1/

Egon Elbre

unread,
Jun 15, 2015, 6:07:24 PM6/15/15
to object-co...@googlegroups.com


On Tuesday, June 16, 2015, Egon Elbre <egon...@gmail.com> wrote:


On Monday, June 15, 2015, Matthew Browne <mbro...@gmail.com> wrote:
On 6/15/15 2:37 PM, Egon Elbre wrote:
On Monday, June 15, 2015, Matthew Browne <mbro...@gmail.com> wrote:
You have to call the function in order for it to work. Source() === source returns true.

If you call Source() with no arguments, it returns the source object, or if you call it with arguments then the first argument is the name of the method (or property) and the remaining arguments (if any) get passed as arguments to the method.

It's unusual to have to put parentheses after every role identifier but does that make it an invalid DCI implementation? I don't think so...if so, why?


By the same argument why wrapper is an invalid DCI implementation. This implementation is just a wrapper in disugise. In this case the wrapper is a function instead of an object.
I don't think it's the same as a wrapper implementation.

I agree that it's not exactly the same. Something between name mangling and wrapper is more appropriate.

But just because you make impossible to access the wrapper, doesn't mean it's not there. But I agree that it's safer than an accessible wrapper. It feels like something that can break under some circumstances, e.g. eval("Sou" + "rce"). Than again I can't think of a real world case where this could happen.

OK, I think I have one: mixing it with libraries that generate code, e.g. https://github.com/egonelbre/jstricks/blob/master/slide_code/lambda.js

I've seen such libraries in the wild wild javascript world. Although I can't remember what they were called. Also I use sometimes code generation to inline things, e.g. https://github.com/loov/jsfx/blob/master/jsfx.js#L935

Matthew Browne

unread,
Jun 16, 2015, 10:29:41 AM6/16/15
to object-co...@googlegroups.com
I came up with an alternative approach:
http://jsfiddle.net/mbrowne/13jg3507/2/

It has at least one flaw not shared by my previous implementation (passing role players to non-Context functions, as mentioned in a code comment), but the syntax is a lot nicer. Note that instance methods do not have access to role methods. It works by requiring that all roles be accessed via a 'roles' object, which calls a getter method under the hood to set the current context and role name -- but those are reset as soon as a role method is called. If the 'roles.' prefix is considered too verbose, then it could be aliased to something else, e.g. '$.' or '_.'.

It may have other flaws...I'd be interested to hear how you all think it compares to my previous version.

Egon Elbre

unread,
Jun 16, 2015, 11:35:36 AM6/16/15
to object-co...@googlegroups.com
On Tuesday, 16 June 2015 17:29:41 UTC+3, Matthew Browne wrote:
I came up with an alternative approach:
http://jsfiddle.net/mbrowne/13jg3507/2/

It has at least one flaw not shared by my previous implementation (passing role players to non-Context functions, as mentioned in a code comment), but the syntax is a lot nicer. Note that instance methods do not have access to role methods. It works by requiring that all roles be accessed via a 'roles' object, which calls a getter method under the hood to set the current context and role name -- but those are reset as soon as a role method is called. If the 'roles.' prefix is considered too verbose, then it could be aliased to something else, e.g. '$.' or '_.'.


Doesn't work with callbacks, which from JS standpoint is a bigger issue than not supporting eval.
e.g. add window.setTimeout(function(){ roles.self.withdraw(); }, 100) into transferOut and you'll get "cannot read property 'withdraw' of undefined".

Also there seems to be some kind of bug with binding... e.g. try

roles.self.withdraw();
roles.self.withdraw();

It may have other flaws...I'd be interested to hear how you all think it compares to my previous version. 

It substitutes some issues for other issues. Essentially they both have problems that may cause non-obvious issues, which means I wouldn't use either. I would rather use a simple wrapper, with it's know issues, or do the name-mangling manually. Neither of them is perfect, but the issues are clear and known in JS.

Just to clarify things from my JS research/experiments...

1. Premise, role names (and "this") should equal their players. This is to make absolutely clear that there are no object identity issues. Otherwise you can start getting all sorts of issues e.g. with eval / callbacks.

2. To make it exactly fit JS, the code for method calls should look like "role.method(...)". 
To make it work there are two approaches:

2.1 Inject the method into the object - either adding them directly to the object or modify the prototype chain, or inject them into one of the object prototypes... that part is pretty easy. However, once you add it, you need to also remove so that there aren't any memory leaks and callbacks work. When you use manual or automatic removal of those methods, there will be a potential problem where a callback returns and the context has already been destroyed. When you don't remove them you'll get a memory leak - and I didn't find any way to make JS runtime automatically collect the unused contexts and methods. Even if it eventually collects it there is also possibility that when you do two Transfers in a row the GC hasn't triggered yet and the methods in the first Transfer are still bound - hence you'll get an invalid method clash.

2.2 Do a source transformation. This makes you have issues with debuggability and integrating with existing tooling. This also has a problem that eval("Source.withdraw()") won't work - the method call would resolve to the Object and when you don't allow method shadowing, this will throw an error.

This basically means that source transformation has the least amount of problems.

There are of course possibilities for emulating DCI, e.g. use Proxy object or manually mangling of method calls.

+ Egon

Matthew Browne

unread,
Jun 16, 2015, 11:52:14 AM6/16/15
to object-co...@googlegroups.com
On 6/16/15 11:35 AM, Egon Elbre wrote:
On Tuesday, 16 June 2015 17:29:41 UTC+3, Matthew Browne wrote:
I came up with an alternative approach:
http://jsfiddle.net/mbrowne/13jg3507/2/

It has at least one flaw not shared by my previous implementation (passing role players to non-Context functions, as mentioned in a code comment), but the syntax is a lot nicer. Note that instance methods do not have access to role methods. It works by requiring that all roles be accessed via a 'roles' object, which calls a getter method under the hood to set the current context and role name -- but those are reset as soon as a role method is called. If the 'roles.' prefix is considered too verbose, then it could be aliased to something else, e.g. '$.' or '_.'.


Doesn't work with callbacks, which from JS standpoint is a bigger issue than not supporting eval.
e.g. add window.setTimeout(function(){ roles.self.withdraw(); }, 100) into transferOut and you'll get "cannot read property 'withdraw' of undefined".

Also there seems to be some kind of bug with binding... e.g. try

roles.self.withdraw();
roles.self.withdraw();
Thanks for pointing out those issues...the implementation of 'self' needs some work. If you instead do roles.Source.withdraw() in a callback, or calling it twice in a row, it will work.

It substitutes some issues for other issues. Essentially they both have problems that may cause non-obvious issues, which means I wouldn't use either. I would rather use a simple wrapper, with it's know issues, or do the name-mangling manually. Neither of them is perfect, but the issues are clear and known in JS.
I think it would probably be possible to determine all the issues with this approach so that they are all "known" issues. So I think this implementation might still have a place for those who don't want to use wrappers and also don't want to use source transformation for whatever reason. If I can fix the issues with 'self' then I think we could even post some examples using this implementation on fulloo.info that would be at least as good as the native Ruby examples. On the other hand it might be better to just encourage the use of a source transformation solution and keep this in our back pocket...I suppose it depends on how JS programmers react to adding another step to their build process (I'm guessing that at least 90% of JS programmers wouldn't mind at all).

But I think these implementations may also have value as a model for other languages for which the community might be more resistant to adding a source transformation step...although I'm not sure if these implementations would be possible in other languages.

Egon Elbre

unread,
Jun 16, 2015, 12:26:15 PM6/16/15
to object-co...@googlegroups.com


On Tuesday, 16 June 2015 18:52:14 UTC+3, Matthew Browne wrote:
On 6/16/15 11:35 AM, Egon Elbre wrote:
On Tuesday, 16 June 2015 17:29:41 UTC+3, Matthew Browne wrote:
I came up with an alternative approach:
http://jsfiddle.net/mbrowne/13jg3507/2/

It has at least one flaw not shared by my previous implementation (passing role players to non-Context functions, as mentioned in a code comment), but the syntax is a lot nicer. Note that instance methods do not have access to role methods. It works by requiring that all roles be accessed via a 'roles' object, which calls a getter method under the hood to set the current context and role name -- but those are reset as soon as a role method is called. If the 'roles.' prefix is considered too verbose, then it could be aliased to something else, e.g. '$.' or '_.'.


Doesn't work with callbacks, which from JS standpoint is a bigger issue than not supporting eval.
e.g. add window.setTimeout(function(){ roles.self.withdraw(); }, 100) into transferOut and you'll get "cannot read property 'withdraw' of undefined".

Also there seems to be some kind of bug with binding... e.g. try

roles.self.withdraw();
roles.self.withdraw();
Thanks for pointing out those issues...the implementation of 'self' needs some work. If you instead do roles.Source.withdraw() in a callback, or calling it twice in a row, it will work.

You know what... that actually might work quite well... I missed some details in the implementation before. Also found some additional issues, you can't have undefined to be a role player that has methods. 

Anyways, I would make the syntax look like:

var TransferMoney = function(source, destination, amount) {
var transfer = dci.Roles({
Source: {
player: source,
transferOut: function() {
transfer.Source.withdraw();
transfer.Destination.deposit();
},
withdraw: function() {
transfer.Source.decreaseBalance(transfer.Amount);
}
},
Destination: {
player: destination,
deposit: function() {
transfer.Destination.increaseBalance(transfer.Amount);
}
},
Amount: {
player: amount
}
});

transfer.Source.transferOut();
);

I would get rid of "self" and leave receiver in role methods be undefined; i.e. you always have to call role by name. I find it clearer than using "R.self".
It substitutes some issues for other issues. Essentially they both have problems that may cause non-obvious issues, which means I wouldn't use either. I would rather use a simple wrapper, with it's know issues, or do the name-mangling manually. Neither of them is perfect, but the issues are clear and known in JS.
I think it would probably be possible to determine all the issues with this approach so that they are all "known" issues. So I think this implementation might still have a place for those who don't want to use wrappers and also don't want to use source transformation for whatever reason. If I can fix the issues with 'self' then I think we could even post some examples using this implementation on fulloo.info that would be at least as good as the native Ruby examples. On the other hand it might be better to just encourage the use of a source transformation solution and keep this in our back pocket...I suppose it depends on how JS programmers react to adding another step to their build process (I'm guessing that at least 90% of JS programmers wouldn't mind at all).

I would have to agree with the statistic, although I'm one of is annoyed with complicated build scripts :).

But I think these implementations may also have value as a model for other languages for which the community might be more resistant to adding a source transformation step...although I'm not sure if these implementations would be possible in other languages.

Maybe, although I can't think of a language where it would fit nicely.

+ Egon

Matthew Browne

unread,
Jun 16, 2015, 12:37:04 PM6/16/15
to object-co...@googlegroups.com
On 6/16/15 11:35 AM, Egon Elbre wrote:
Just to clarify things from my JS research/experiments...

1. Premise, role names (and "this") should equal their players. This is to make absolutely clear that there are no object identity issues. Otherwise you can start getting all sorts of issues e.g. with eval / callbacks.

2. To make it exactly fit JS, the code for method calls should look like "role.method(...)". 
To make it work there are two approaches:

2.1 Inject the method into the object - either adding them directly to the object or modify the prototype chain, or inject them into one of the object prototypes... that part is pretty easy. However, once you add it, you need to also remove so that there aren't any memory leaks and callbacks work. When you use manual or automatic removal of those methods, there will be a potential problem where a callback returns and the context has already been destroyed. When you don't remove them you'll get a memory leak - and I didn't find any way to make JS runtime automatically collect the unused contexts and methods. Even if it eventually collects it there is also possibility that when you do two Transfers in a row the GC hasn't triggered yet and the methods in the first Transfer are still bound - hence you'll get an invalid method clash.

2.2 Do a source transformation. This makes you have issues with debuggability and integrating with existing tooling. This also has a problem that eval("Source.withdraw()") won't work - the method call would resolve to the Object and when you don't allow method shadowing, this will throw an error.
There is one other possible approach I didn't mention...you could generate a unique ID for each context instance and pass that context ID with every method call, but I considered that to be too ugly to be worth consideration, and it violates your premise #2.

As to the garbage collection problem, I investigated your earlier example using WeakMap() and I think I know why it didn't work...WeakMaps are non-enumerable, so using a WeakMap with Context instances as keys doesn't solve the GC problem -- in order to retrieve the Context, you have to already have a reference to it, which defeats the whole point. And that's unlikely to change in any future version of Javascript, because at least according to an answer I found on StackOverflow (which was citing an official reference if I recall correctly) it would cause security issues to allow WeakMaps to be enumerable (apparently you don't want hackers to be able to check whether a variable has been garbage collected).

But I think this is only an issue if you are storing a reference to the actual Context instance; if you're only storing a reference to role methods then the memory footprint is pretty low. Objects in JS store references to methods all the time anyway. So I propose using a regular Map() and instead of using the actual Context instances as keys, use "reflection Contexts" - objects whose sole purpose is to store info about the Context and its role methods. You wouldn't be able to use reflection to look up the actual Context instance when reflecting on an object, but the reflection Context could still store all the role methods and the type of the Context. Importantly, the reflection Context should not store bindings, only role methods. Otherwise you'll have GC issues on that end (i.e. you don't want reflection Contexts to hold onto references to role players and prevent them from being GC'd).

I experimented with this a couple weeks ago and didn't get a chance to post about it yet; I can post some example code if you're interested.

Egon Elbre

unread,
Jun 16, 2015, 1:36:50 PM6/16/15
to object-co...@googlegroups.com
My goal was to isolate the GC-able context, essentially

role players have a weak pointer to --> context
and context can point back to players

The Context has hard pointers internally, but once the context is over, the only things referring to the Context are weak-pointers. Hence it should be possible to GC the context and the methods and roles inside it. tl;dr; all the non-weak pointers to Context are inside the Context.


I experimented with this a couple weeks ago and didn't get a chance to post about it yet; I can post some example code if you're interested.

If you have solution to the GCing problem and while being able to see the roles being played I would love to see it.

Matthew Browne

unread,
Jun 16, 2015, 11:37:59 PM6/16/15
to object-co...@googlegroups.com
Here's a version that includes role binding info both in the role players and in the "reflection Context" objects I mentioned in my last email:
http://jsfiddle.net/mbrowne/13jg3507/4/

The reflection Contexts are never garbage collected as long as some object that played a role in the corresponding Context still exists, but I don't think it matters because the memory footprint is low. The role methods are only stored once per Context function.

I haven't updated the code that generates the role method delegator functions yet, but I'm pretty sure it would be possible to allow for name conflicts between roles (including roles in different Contexts) thanks to the way I've organized the role methods (first by Context instance, then by role name).

As to the GC issues, I explained in my previous email why I think this implementation solves that, but I'm not sure how to test it correctly to make sure...I guess by creating thousands of objects?

Two drawbacks of the reflection to look up role bindings:

1. You can't use a Context instance to directly look up the objects currently bound to roles; you need to have a reference to an object and then you can check to see what roles it's bound to.

So if you want to see role bindings, it would generally make the most sense to just look in the object's __roles property.

2. When inspecting an object, it doesn't tell you which role bindings are currently active; it simply lists all of them (including role bindings from Contexts that no longer exist). It may be possible to have it exclude Contexts that no longer exist (i.e. that have been GC'd) with further use of WeakMaps.

With respect to #2, I experimented with Trygve's suggestion to use the execution stack (using this library), but this seems not to be useful without ugly hacks since the JS execution stack doesn't allow you to see whether or not the function that was called was inside a particular Context function. The best I was able to accomplish was using line numbers to see if the call to the reflection facility was literally within the starting and ending lines of the Context, which of course would require a preprocessing step to determine what those line numbers are. So I think we can probably rule out that idea as impractical for JS.

But I'm not sure there's actually a need for the reflection API to tell you which roles are currently active; I think it should be obvious to the programmer that they're active from within the Context containing the roles, and not active outside of it (since roles are always private to Contexts).

Egon Elbre

unread,
Jun 17, 2015, 5:47:49 AM6/17/15
to object-co...@googlegroups.com
On Wed, Jun 17, 2015 at 6:37 AM, Matthew Browne <mbro...@gmail.com> wrote:
Here's a version that includes role binding info both in the role players and in the "reflection Context" objects I mentioned in my last email:
http://jsfiddle.net/mbrowne/13jg3507/4/

The reflection Contexts are never garbage collected as long as some object that played a role in the corresponding Context still exists, but I don't think it matters because the memory footprint is low. The role methods are only stored once per Context function.

I haven't updated the code that generates the role method delegator functions yet, but I'm pretty sure it would be possible to allow for name conflicts between roles (including roles in different Contexts) thanks to the way I've organized the role methods (first by Context instance, then by role name).

As to the GC issues, I explained in my previous email why I think this implementation solves that, but I'm not sure how to test it correctly to make sure...I guess by creating thousands of objects?

Add method clashing checks, to see whether the things get GC-d in time.
window.setInterval(function(){ for(var i = 0; i < 1000; i++){ TransferMoney(src,dst,10) } }, 500)

Also make TransferMoney call itself recursively (whether there are other side-effects... although in practice it shouldn't come up often.)

Then monitor the page memory usage stats.
 

Two drawbacks of the reflection to look up role bindings:

1. You can't use a Context instance to directly look up the objects currently bound to roles; you need to have a reference to an object and then you can check to see what roles it's bound to.

So if you want to see role bindings, it would generally make the most sense to just look in the object's __roles property.

2. When inspecting an object, it doesn't tell you which role bindings are currently active; it simply lists all of them (including role bindings from Contexts that no longer exist). It may be possible to have it exclude Contexts that no longer exist (i.e. that have been GC'd) with further use of WeakMaps.

I'm tending to lean towards that it's not possible.
 

With respect to #2, I experimented with Trygve's suggestion to use the execution stack (using this library), but this seems not to be useful without ugly hacks since the JS execution stack doesn't allow you to see whether or not the function that was called was inside a particular Context function. The best I was able to accomplish was using line numbers to see if the call to the reflection facility was literally within the starting and ending lines of the Context, which of course would require a preprocessing step to determine what those line numbers are. So I think we can probably rule out that idea as impractical for JS.

But I'm not sure there's actually a need for the reflection API to tell you which roles are currently active; I think it should be obvious to the programmer that they're active from within the Context containing the roles, and not active outside of it (since roles are always private to Contexts).

Yes, I tend to think the same.

Matthew Browne

unread,
Jun 17, 2015, 8:20:06 AM6/17/15
to object-co...@googlegroups.com
On 6/17/15 5:47 AM, Egon Elbre wrote:
On Wed, Jun 17, 2015 at 6:37 AM, Matthew Browne <mbro...@gmail.com> wrote:
Here's a version that includes role binding info both in the role players and in the "reflection Context" objects I mentioned in my last email:
http://jsfiddle.net/mbrowne/13jg3507/4/

The reflection Contexts are never garbage collected as long as some object that played a role in the corresponding Context still exists, but I don't think it matters because the memory footprint is low. The role methods are only stored once per Context function.

I haven't updated the code that generates the role method delegator functions yet, but I'm pretty sure it would be possible to allow for name conflicts between roles (including roles in different Contexts) thanks to the way I've organized the role methods (first by Context instance, then by role name).

As to the GC issues, I explained in my previous email why I think this implementation solves that, but I'm not sure how to test it correctly to make sure...I guess by creating thousands of objects?

Add method clashing checks, to see whether the things get GC-d in time.
window.setInterval(function(){ for(var i = 0; i < 1000; i++){ TransferMoney(src,dst,10) } }, 500)
I don't think this test would be relevant unless I succeed in making the role binding map automatically remove GC'd Contexts, right? Which I think is probably not possible, as you said, at least not in the browser (I found a good description of the issue here: http://stackoverflow.com/a/25631962/560114). But I think it would be possible with the help of this module for node.js I just found:
https://github.com/TooTallNate/node-weak

Also make TransferMoney call itself recursively (whether there are other side-effects... although in practice it shouldn't come up often.)

Then monitor the page memory usage stats.
Here are the results:



I ran the version of the code that does not store reflection info to compare and the percentages looked pretty much the same, (in particular the count for "system / Context" - which indicates the number of instances of TransferMoney - was still at 11%), so it seems that the way I'm storing reflection info has not prevented garbage collection.

Matthew Browne

unread,
Jun 17, 2015, 5:40:12 PM6/17/15
to object-co...@googlegroups.com
In other news, there's now a project (developed by Facebook) to add optional static typing to Javascript:
http://flowtype.org/

...so my future efforts will probably be focused mainly on Javascript itself rather than compile-to-JS languages like TypeScript. There's also a flow plugin for Babel and acorn that I'm planning to use as a model for a DCI plugin (and I got some tips from the creator of that plugin so I now have an idea of how to implement 'role' and 'context' keywords as an acorn plugin rather than having to fork it).

Matthew Browne

unread,
Jun 18, 2015, 6:07:39 AM6/18/15
to object-co...@googlegroups.com
Hi Egon,
Here's some code I'm considering as being an official example for this new implementation (with some changes inspired by your feedback):

var dci = require('simple-dci'),
    Account = require('Account');

/**
 * Context for Transfer Money use case
 *
 * @param {Account} sourceAccount
 * @param {Account} destinationAccount
 * @param {number} amount
 */
module.exports = dci.Context(function TransferMoney(sourceAccount, destinationAccount, amount) {
    var ctx = roles();
   
    ctx.source.withdraw();
    ctx.destination.deposit();
   
    function roles() {
        return dci.Roles(TransferMoney, {
            source: {
                player: sourceAccount
              , contract: Account
              , withdraw: function() {
                    if (ctx.source.balance < ctx.amount) {
                        throw new Error('Insufficient funds');
                    }
                    ctx.source.decreaseBalance(ctx.amount);
                }
            }
   
          , destinatinon: {
                player: sourceAccount
              , contract: Account
              , deposit: function() {
                    ctx.destinatinon.increaseBalance(ctx.amount);
                }
            }
   
          , amount: {
                player: amount
              , contract: Number
            }
        });
    }
});


I agree that it looked nice with transfer.source and transfer.destination but I ctx is just so much shorter to type ;) The downside would be in a Context with multiple trigger methods, where ctx should probably refer to the actual instance, in which case it wouldn't be a good idea to be adding roles to it since it would expose those roles outside the Context.

I also changed it so the main function logic is above the roles (thanks to the roles() function) but that's just a personal preference.

Perhaps the most notable change is the introduction of role-object contracts, which I realized I can enforce at role-binding time. contract could also be set to a function for custom contract checking logic.

I also got rid of the transferOut() function and moved that logic to the main function, since I don't think the transfer logic really belongs to the source any more than it does the destination. It could go either way though and I might continue to use my earlier transferOut() version in the future since it's a simple test of a role calling both another role and itself.

The only thing (about the syntax) that still bothers me a bit is the lack of a 'self' identifier; the ability to use 'self' or 'this' is a useful shorthand that many OO programmers are accustomed to. On the other hand, the explicit use of the role name would be a good thing in some cases anyway since it could add clarity. this of course correctly refers to the role player, but you can only call instance methods on it which I think is inconsistent.

Egon Elbre

unread,
Jun 18, 2015, 7:00:40 AM6/18/15
to object-co...@googlegroups.com


On Thursday, 18 June 2015 13:07:39 UTC+3, Matthew Browne wrote:
Hi Egon,
Here's some code I'm considering as being an official example for this new implementation (with some changes inspired by your feedback):

var dci = require('simple-dci'),
    Account = require('Account');

/**
 * Context for Transfer Money use case
 *
 * @param {Account} sourceAccount
 * @param {Account} destinationAccount
 * @param {number} amount
 */
module.exports = dci.Context(function TransferMoney(sourceAccount, destinationAccount, amount) {
    var ctx = roles();
   
    ctx.source.withdraw();
    ctx.destination.deposit();
   
    function roles() {
        return dci.Roles(TransferMoney, {

Am I missing something obvious; i.e. did you need to pass TransferMoney into "Roles"?
 
            source: {
                player: sourceAccount
              , contract: Account
              , withdraw: function() {
                    if (ctx.source.balance < ctx.amount) {
                        throw new Error('Insufficient funds');
                    }
                    ctx.source.decreaseBalance(ctx.amount);
                }
            }
   
          , destinatinon: {
                player: sourceAccount
              , contract: Account
              , deposit: function() {
                    ctx.destinatinon.increaseBalance(ctx.amount);
                }
            }
   
          , amount: {
                player: amount
              , contract: Number
            }
        });
    }
});


I agree that it looked nice with transfer.source and transfer.destination but I ctx is just so much shorter to type ;) The downside would be in a Context with multiple trigger methods, where ctx should probably refer to the actual instance, in which case it wouldn't be a good idea to be adding roles to it since it would expose those roles outside the Context.

That's one of the reasons I didn't call it context, the context is the function - not the thing that contains roles. i.e. naming the rolemap as "transfer" simply made code nice to read.
 

I also changed it so the main function logic is above the roles (thanks to the roles() function) but that's just a personal preference.

Sure, I  can understand the reasoning.
 

Perhaps the most notable change is the introduction of role-object contracts, which I realized I can enforce at role-binding time. contract could also be set to a function for custom contract checking logic.

Here's the funny thing, while typing it out... I thought of adding it in a similar way, although I tried:

contract: ["increaseBalance"]
or
contract: { increaseBalance: "method" }

But it didn't look nice to me... Somehow missed the obvious - using the constructor as the contract.
 

I also got rid of the transferOut() function and moved that logic to the main function, since I don't think the transfer logic really belongs to the source any more than it does the destination. It could go either way though and I might continue to use my earlier transferOut() version in the future since it's a simple test of a role calling both another role and itself.

The only thing (about the syntax) that still bothers me a bit is the lack of a 'self' identifier; the ability to use 'self' or 'this' is a useful shorthand that many OO programmers are accustomed to.
On the other hand, the explicit use of the role name would be a good thing in some cases anyway since it could add clarity. this of course correctly refers to the role player, but you can only call instance methods on it which I think is inconsistent.

I'm happy to see it removed :D, although I can understand the reluctance of removing it.

But the main reasons why I removed were 
1. it complicates things inside the implementation (the roles.self isn't constantly changing; also with callbacks there might be issues etc.)
2. the inconsistency between this and self.

Andreas Söderlund

unread,
Jun 18, 2015, 7:32:42 AM6/18/15
to object-co...@googlegroups.com
Hello Matt, it's looking really nice now! I was hoping for some syntax improvements, I think a clear syntax is one of the most important things to have. After all the code is a mental model itself, when matched gives this Matrix moment "I don't even see the code". (https://www.youtube.com/watch?v=qAYXgbSlSv0)

A few comments:

module.exports = dci.Context(function TransferMoney(sourceAccount, destinationAccount, amount) {
    var ctx = roles();
   
    ctx.source.withdraw();
    ctx.destination.deposit();
   
    function roles() {
        return dci.Roles(TransferMoney, {

Same question as Egon here, do you need to pass TransferMoney? Also what about the naming: ctx = roles()? Shouldn't it be more like ctx = context()?

Having the context object passed as a parameter to the function would be nice, but I don't know if it's possible:

module.exports = dci.Context(function(ctx, sourceAccount, destinationAccount, amount) {
...

 
            source: {
                player: sourceAccount
              , contract: Account

It would be nice to avoid convention-based declarations like "player" and "contract", which also makes them reserved RoleMethod names I guess? I was fortunate to avoid that in Haxe because of AST rewriting, but I don't know if it can be done here? Perhaps with a function like

source: dci.Role(sourceAccount, Account, {
  withdraw: function() {
    ...
  }
});
 
              , withdraw: function() {
                    if (ctx.source.balance < ctx.amount) {
                        throw new Error('Insufficient funds');
                    }
                    ctx.source.decreaseBalance(ctx.amount);

Isn't object communication a major point? By moving ctx.destination.deposit() to the main function, you've made things very procedural. We have a FAQ question for that, and the scenario-to-algorithm mapping (Lean Architecture, chapter 9) is on the same track with for example "Source account requests that Destination account increase its balance". 
 
          , destinatinon: {
                player: sourceAccount
              , contract: Account
              , deposit: function() {
                    ctx.destinatinon.increaseBalance(ctx.amount);
                }
            }

,hmm ,comma first is a matter of style I guess ,but for me it looks a bit strange. :)


/Andreas

Matthew Browne

unread,
Jun 18, 2015, 7:36:39 AM6/18/15
to object-co...@googlegroups.com
On 6/18/15 7:00 AM, Egon Elbre wrote:
On Thursday, 18 June 2015 13:07:39 UTC+3, Matthew Browne wrote:
        return dci.Roles(TransferMoney, {

Am I missing something obvious; i.e. did you need to pass TransferMoney into "Roles"?
In my latest jsfiddle I stored the role methods in TransferMoney.roleMethods (ctxFn.roleMethods); come to think of it that property should probably be hidden and called cxtFn.__roles or ctxFn.__roleDecls. This makes it possible to store only one copy of the role methods per Context function, which is more memory efficient. In order to allow name conflicts between roles/contexts and for reflection it has to store a permanent reference from the object to all its role methods (present and past), so it could take up a good bit of memory in some cases if it kept a separate copy of the role methods for every Context invocation / instance.

It's possible that the programmer might declare the role methods in a dynamic way that would result in differences in the role methods amongst instances of the same Context function, so I'm planning to have it at least check to make sure all the role and method names are the same before assuming that it's the same set of role methods as the previous instance of that Context. That way I can still make it more memory efficient 99% of the time.

Matthew Browne

unread,
Jun 18, 2015, 8:14:42 AM6/18/15
to object-co...@googlegroups.com
On 6/18/15 7:32 AM, Andreas Söderlund wrote:
Hello Matt, it's looking really nice now!
Thanks :)

I was hoping for some syntax improvements, I think a clear syntax is one of the most important things to have.
I agree.

After all the code is a mental model itself, when matched gives this Matrix moment "I don't even see the code". (https://www.youtube.com/watch?v=qAYXgbSlSv0)

A few comments:

module.exports = dci.Context(function TransferMoney(sourceAccount, destinationAccount, amount) {
    var ctx = roles();
   
    ctx.source.withdraw();
    ctx.destination.deposit();
   
    function roles() {
        return dci.Roles(TransferMoney, {

Same question as Egon here, do you need to pass TransferMoney? Also what about the naming: ctx = roles()? Shouldn't it be more like ctx = context()?

Having the context object passed as a parameter to the function would be nice, but I don't know if it's possible:

module.exports = dci.Context(function(ctx, sourceAccount, destinationAccount, amount) {
...
I agree that ctx = roles() sends the wrong message to the programmer; thanks for pointing it out. As to the above line of code, I'm not sure what you would pass as ctx there - I think the Context instance should either be this (for constructor functions) or a new object each time the function is called (for non-constructor functions), which the library could create if the programmer doesn't pass it to dci.Roles().

Maybe this would work better?:

var ctx = {};
dci.Roles(TransferMoney, ctx, {
    //role declarations
});

            source: {
                player: sourceAccount
              , contract: Account

It would be nice to avoid convention-based declarations like "player" and "contract", which also makes them reserved RoleMethod names I guess? I was fortunate to avoid that in Haxe because of AST rewriting, but I don't know if it can be done here? Perhaps with a function like

source: dci.Role(sourceAccount, Account, {
  withdraw: function() {
    ...
  }
});
Or:

source: {
    player: sourceAccount,
    contract: Account,
    methods: {
        withdraw: function() {
            ...
        }
    }
}


Or just:

source: {
    $player: sourceAccount,
    $contract: Account,
    withdraw: function() {
        ...
    }
}

 
              , withdraw: function() {
                    if (ctx.source.balance < ctx.amount) {
                        throw new Error('Insufficient funds');
                    }
                    ctx.source.decreaseBalance(ctx.amount);

Isn't object communication a major point? By moving ctx.destination.deposit() to the main function, you've made things very procedural. We have a FAQ question for that, and the scenario-to-algorithm mapping (Lean Architecture, chapter 9) is on the same track with for example "Source account requests that Destination account increase its balance".
Yes, object communication is a major point, but I think that source.transferOut() only makes sense if there's also destination.transferIn(). I think the methods source.withdraw() and destination.deposit() (as in Rune's Marvin example) are nice reflections of the mental model, but then also having both source.transferOut() and destination.transferIn() would make the code unnecessarily verbose. So in Marvin Rune just made it source.transfer(), but he agreed with my criticism that it's not clear why a "transfer" method would need to be a role method at all, so he and I have been using source.transferOut().

Arbitrarily putting the transfer logic in the Source role is perhaps a weakness of the money transfer example (if you want to also have source.withdraw() and destination.deposit()). An example where the main logic more clearly belongs to one of the roles might make a better first example. I do think it's OK to have some short methods in the Context (or in this case the Context function itself) that call a few role methods directly rather than necessarily delegating to a role method for the entire operation - more like a mediator pattern. As a rule of thumb, the more logic that can be put in roles, the better, but only if it makes the code more clear; in this case I don't see a strong advantage of using source.transferOut() or source.transferFrom().

Rune seems to agree with me:

https://github.com/runefs/maroon/blob/master/test/examples/money_transfer_test.rb

https://groups.google.com/d/msg/object-composition/Zc-aVmFpIgA/i4ZSKDLk820J:
I've tried out various approaches where the connection between two roles are not methods. They are connections with a role in either end.

Source ---- transfer  ----> destination

The syntax for declaring the connections are somewhat unknown, but the idea is that at both ends you can find a method called transfer one declared as outgoing and the other declared as inbound. That is unrelated to the shadowing problem but the idea might spawn other ideas that could help. The point of declaring connections would be to make the I/O part of the interaction graph more explicit which I find the current implementations do not
https://groups.google.com/d/msg/object-composition/2F6kwUpb0FQ/YAyEkaeALPYJ:
Where does the part of an interaction that is no more related to one role than any other role in the interaction belong and how does that make it obviously which nodes are connected to which in the interaction graph? We are claiming that DCI is better than DDD because in DDD something that belongs together is split (somewhat arbitrarily) into various classes. If we want to hold on to that claim I think we should be able to answer the above question
Some of my musings on this:
https://groups.google.com/d/msg/object-composition/2F6kwUpb0FQ/OwGZ8un0Ch0J


 
          , destinatinon: {
                player: sourceAccount
              , contract: Account
              , deposit: function() {
                    ctx.destinatinon.increaseBalance(ctx.amount);
                }
            }

,hmm ,comma first is a matter of style I guess ,but for me it looks a bit strange. :)
I suppose it's a bit too unconventional...it helps avoid syntax errors due to trailing commas, but I'll change it to avoid such reactions...


/Andreas

Matthew Browne

unread,
Jun 18, 2015, 8:25:04 AM6/18/15
to object-co...@googlegroups.com
If keeping source.withdraw() and destination.deposit(), I would be more open to this variation:

module.exports = dci.Context(function TransferMoney(sourceAccount, destinationAccount, amount) {
    var ctx = {};
    dci.initRoles(TransferMoney, roleDefs(), ctx);
   
    ctx.bank.transfer();
   
    function rolesDefs() {
        return {
            bank: {
                $player: ctx,
                transfer: function() {
                    ctx.source.withdraw();
                    ctx.destination.deposit();
                }
            },

           
            source: {
                $player: sourceAccount,
                $contract: Account,
                withdraw: function() {
                    if (ctx.source.balance < ctx.amount) {
                        throw new Error('Insufficient funds');
                    }
                    ctx.source.decreaseBalance(ctx.amount);
                }
            },
           
            destinatinon: {
                $player: sourceAccount,
                $contract: Account,

                deposit: function() {
                    ctx.destinatinon.increaseBalance(ctx.amount);
                }
            },
           
            amount: {
                $player: amount,
                $contract: Number
            }
        };
    }
});

Matthew Browne

unread,
Jun 18, 2015, 8:33:51 AM6/18/15
to object-co...@googlegroups.com
BTW to Andreas -- given your preference for CoffeeScript over
Javascript, I'm guessing this new language might interest you:
http://breuleux.github.io/earl-grey/

It's closer to Python whereas I think CoffeeScript is closer to Ruby,
but it seems that CoffeeScript will not be supporting newer Javascript
features unless someone puts new funding into the CoffeeScript-redux
project. Earl Grey on the other hand already supports a lot of newer JS
features (including syntax similar to the proposed ES7 async/await
feature). I learned about it from this thread, which you might find
interesting:

https://github.com/michaelficarra/CoffeeScriptRedux/issues/338

Matthew Browne

unread,
Jun 18, 2015, 8:53:23 AM6/18/15
to object-co...@googlegroups.com
Note: If not in strict mode, I could use aruments.callee.caller to get a reference to the Context function so it wouldn't need to be passed explicitly. But a lot of people are using strict mode these days (and there are some good reasons for that)...

Or I could use Error() and look up the context function from the stack trace (or the .stack property in Chrome), but I'm not sure what the performance implications of that would be...

I just thought of one other option...since I was planning to compare the role methods anyway to check if the programmer declared them in a dynamic way (see above), I could go ahead and check each method in each role, and if all the role/method names and source code for each method was the same, it's presumably the same Context function. But again, there could be negative effects on performance from all the source code string comparisons.

Matthew Browne

unread,
Jun 18, 2015, 9:00:46 AM6/18/15
to object-co...@googlegroups.com
Another alternative would be to instruct the programmer that if they want the best memory efficiency, they should declare the role methods outside the Context, e.g.:

module.exports = dci.Context(function TransferMoney(sourceAccount, destinationAccount, amount) {
    var ctx = dci.initContext(roleDefs);
    ...
});

var roleDefs = {
    ...
}


But do like having the role definitions inside the Context function; it just looks right from the perspective that roles should be private to Contexts (even though roleDefs would be private to the TransferMoney module either way).

So as a final alternative, the Context function could be an optional argument; if provided, it would be more memory efficient.

Egon Elbre

unread,
Jun 18, 2015, 9:07:49 AM6/18/15
to object-co...@googlegroups.com


On Thursday, 18 June 2015 16:00:46 UTC+3, Matthew Browne wrote:
Another alternative would be to instruct the programmer that if they want the best memory efficiency, they should declare the role methods outside the Context, e.g.:

module.exports = dci.Context(function TransferMoney(sourceAccount, destinationAccount, amount) {
    var ctx = dci.initContext(roleDefs);
    ...
});

var roleDefs = {
    ...
}


But do like having the role definitions inside the Context function; it just looks right from the perspective that roles should be private to Contexts (even though roleDefs would be private to the TransferMoney module either way).

So as a final alternative, the Context function could be an optional argument; if provided, it would be more memory efficient.

I don't think worrying about memory efficiency in this implementation makes sense? Or will there be a large memory leak, if you don't do this? This isn't a high-performance implementation anyways due to the changing of properties when getting roles... To me it looks like it makes things more complicated without clear (real-world) benefit.

Matthew Browne

unread,
Jun 18, 2015, 9:27:35 AM6/18/15
to object-co...@googlegroups.com
On 6/18/15 9:07 AM, Egon Elbre wrote:
On Thursday, 18 June 2015 16:00:46 UTC+3, Matthew Browne wrote:
Another alternative would be to instruct the programmer that if they want the best memory efficiency, they should declare the role methods outside the Context, e.g.:

module.exports = dci.Context(function TransferMoney(sourceAccount, destinationAccount, amount) {
    var ctx = dci.initContext(roleDefs);
    ...
});

var roleDefs = {
    ...
}


But do like having the role definitions inside the Context function; it just looks right from the perspective that roles should be private to Contexts (even though roleDefs would be private to the TransferMoney module either way).

So as a final alternative, the Context function could be an optional argument; if provided, it would be more memory efficient.

I don't think worrying about memory efficiency in this implementation makes sense? Or will there be a large memory leak, if you don't do this? This isn't a high-performance implementation anyways due to the changing of properties when getting roles... To me it looks like it makes things more complicated without clear (real-world) benefit.
If I don't do this, then there will be a separate copy of all the role methods for each invocation of the Context constructor, and those role methods will never be garbage collected, at least not in my planned implementation allowing for reflection and name conflicts amongst different roles / Contexts. Or to be more precise, they won't be GC'd unless all objects that played roles in them are first GC'd.

But maybe that still wouldn't be enough memory to worry about, except in some edge cases...

The memory issue would become moot if name conflicts between different roles / contexts were completely forbidden as Cope proposed, but I'm not convinced that we need to enforce such a strict rule and I think there are legitimate cases where such name conflicts should be allowed.

Also, having a reference to the Context function could be useful for reflection, so that when inspecting an object you can see the Context function that corresponds to a given set of roles (otherwise you'd just be looking at a bunch of roles without knowing which contexts they came from).

Matthew Browne

unread,
Jun 18, 2015, 9:44:41 AM6/18/15
to object-co...@googlegroups.com
I guess I don't have to store references to the "reflection Contexts" in the __roles property of each role player. It could be stored like this instead:

player.__roles = {
    roleName: [methods from context instance 1, methods from context instance 2, etc...],
    ...
};

But then I don't think the reflection API would be able to provide any other info about the Context to which those role methods belong, other than maybe the names of the other roles in the Context if those names were injected too. Even if I use a WeakMap with role methods as keys and reflection Contexts as values, that would keep references to the reflection Contexts alive as long as any of the objects that had played roles in them still existed.

Maybe the solution is to not store references to the role methods themselves inside the reflection Context, but only the names of the roles and role methods. That way I could still store references to reflection Contexts in player.__roles without wasting memory. That would limit the ability to reflect on a Context's roles, but it still leaves room to provide a lot of useful reflection info via either a Context or a role-playing object.

Matthew Browne

unread,
Jun 18, 2015, 9:58:05 AM6/18/15
to object-co...@googlegroups.com
Sorry for all the separate emails, but I just thought of a better solution. player.__roles could be stored in this way (note how the "reflection Context" is represented):

Map {
    map key --> {
        //the "reflection Context"
        roles: {
            source: ['withdraw'],
            destination: ['deposit'],
            amount: []
        },
        contextFn: [function] //OPTIONAL - would need to be passed when initializing roles
        ...
    }
    map value --> {
        //the actual role methods that were bound to this object
        source: {
            withdraw: [function]
        }
    }
}


Whereas when using the reflection API to look up info about a Context (by passing a Context instance), it would return a richer "reflection Context" that included references to all the role methods in the Context:

{
    roles: {
        source: {
            withdraw: [function]
        },
        destination: {
            deposit: [function]
        }
        amount: {}
    },
    ...
}

Matthew Browne

unread,
Jun 19, 2015, 9:09:23 AM6/19/15
to object-co...@googlegroups.com
How about using 'the', e.g.:

var the = dci.initContext(roles());
the.source.withdraw();
the.destination.deposit();


That way it would make sense for constructor functions too.

I experimented with ways to eliminate the need for 'var the ='. I think this might be the best of the alternatives I tried...I haven't implemented it yet but I'm pretty sure it's possible:

function Account(ledgers) {
    return (function(the) {
        if (!ledgers) ledgers = [];
        initRoles();
       
        this.increaseBalance = function(amount) {
            the.ledgers.addEntry('depositing', amount);
        };
   
        this.decreaseBalance = function(amount) {
            the.ledgers.addEntry('withdrawing', 0 - amount);       
        };
       
        Object.defineProperty(this, 'balance', {get: function() {
            return the.ledgers.getBalance();
        }});
       
        function initRoles() {
            the.ledgers = {
                $player: ledgers,
                $contract: function(ledgers) {
                    //must be an array of LedgerEntry objects
                    return typeCheckArrayItems(ledgers, LedgerEntry);
                },
                addEntry(message, amount) {
                    the.ledgers.push(new LedgerEntry(message, amount));
                },
                getBalance() {
                    var sum = 0;
                    the.ledgers.forEach(function(ledgerEntry) {
                        sum += ledgerEntry.amount;
                    });
                    return sum;
                }
            };
        }
         
    })(dci.initContext(arguments));
});

Egon Elbre

unread,
Jun 19, 2015, 9:25:54 AM6/19/15
to object-co...@googlegroups.com
On Friday, 19 June 2015 16:09:23 UTC+3, Matthew Browne wrote:
How about using 'the', e.g.:

var the = dci.initContext(roles());
the.source.withdraw();
the.destination.deposit();



I think it's better than "ctx", "roles" or "R", but I still like the "transfer" more, although it's more verbose. To me "the", "this", "self" are all noise words that don't mean anything useful.

That way it would make sense for constructor functions too.

I experimented with ways to eliminate the need for 'var the ='. I think this might be the best of the alternatives I tried...I haven't implemented it yet but I'm pretty sure it's possible:

I would agree it would be possible, but I don't think it's worth the effort - it becomes much harder to understand where the functions start and end...
function Account(id, ledger) {
    var account = dci.Roles({
        ID: { $player: id },
        Ledger: {
            $player: ledger,
            $contract: {},
            addEntry: function(message, amount){
                account.Ledger.push(new LedgerEntry(account.ID, message, amount));
            },
            balance: function(){
                var total = 0;
                account.Ledger.forEach(function(entry){
                    if(entry.ID == account.ID){
                        total += entry.amount;
                    }
                });
            }
        }
    });

    return {
        get balance(){
            account.Ledger.balance();
        },
        increaseBalance: function(amount){
            account.Ledger.addEntry("depositing", amount);
        },
        decreaseBalance: function(amount){
            account.Ledger.addEntry("withdrawing", -amount);
        }
    }
};

I also tried "my" instead of "account", which also looks nice.

+ Egon

Matthew Browne

unread,
Jun 19, 2015, 9:36:28 AM6/19/15
to object-co...@googlegroups.com
I think "my" would be better than "account" in this case, not just for
ease of typing but also because what you're returning is an Account
object, and your 'account' variable is not that.

Fortunately the implementation allows for the prefix to be called
whatever you want, so multiple styles can be supported.

BTW is there a reason you chose to make the role name (Ledgers) start
with an upper case letter, given that the implementation allows you to
make it lower case without conflicting with the constructor argument?
The prefix already helps roles to stand out so I think lower case names
are better (for JS); they imply objects rather than classes.

Egon Elbre

unread,
Jun 19, 2015, 9:56:37 AM6/19/15
to object-co...@googlegroups.com
I was fence about it as well... basically what I don't like there is a "random placeholder", it should convey meaning particular to the context - or it shouldn't be there at all.


Fortunately the implementation allows for the prefix to be called
whatever you want, so multiple styles can be supported.

BTW is there a reason you chose to make the role name (Ledgers) start
with an upper case letter, given that the implementation allows you to
make it lower case without conflicting with the constructor argument?
The prefix already helps roles to stand out so I think lower case names
are better (for JS); they imply objects rather than classes.

It's something I have picked up from programming in Go & Delphi... So nothing else than personal preference, I find it nicely highlight the roles. But, I don't think it makes a huge difference, so feel free to substitute them with lower case :)

+ Egon

James O Coplien

unread,
Jun 24, 2015, 7:42:14 AM6/24/15
to object-co...@googlegroups.com
This is an update on my planned work to advance DCI.

I have abandoned my Squeak efforts for want of being able to procure a working version for my Mac. And as I looked at my project to convert Objective-C to DCI I found what many of you are finding in your attempts with other languages, and in particular the recent forays with Javascript. It quickly becomes fragile and is susceptible to incorrect implementations (e.g., accidentally re-introducing wrapper semantics). Further it’s difficult to achieve a syntax that is acceptable, let alone worthy of being excited about. (The adding of extra parenthesis is all-too-reminiscent of the gratuitous curly braces one needs to add in Java to create an anonymous subclass to overcome the type erasure bug in the language — https://code.google.com/p/guava-libraries/wiki/ReflectionExplained).

More broadly, almost all of our work has been based on ports to existing languages, with all of their attendant warts and historical baggage. I became concerned that this is crippling our ability to nurture the dialogue on whither DCI and to refine the computational model instead of just working the engineering issues. The engineering exercises try to introduce as much of the DCI computational model as possible into existing infrastructure, but the incompatibilities leave us always coming up short — at least with respect to the postulates I posted here some time ago. What’s scarier is that these environments usually leave us in a position where we can’t even reason about some of the postulates. I am starting to feel as though we’re going around in circles, as the same issues recur.

I propose to start from scratch, and have designed a new language explicitly with DCI in mind. I want to name the language Trygve but won’t do so until I have his permission. In the mean time it’s named Kant. In the spirit of Smalltalk it will be not just a language but an integrated environment. Both the language and the environment will be meagerly featured, more suitable to a research effort than to the production of any code.

The environment will include an “object machine.” In our work thus far, that part of DCI has been supplanted by the limitations of the run-time environments beneath the respective languages we’ve strived to evolve. I want an environment without excuse for compromise. That means we can have discussions about “what is the right thing to do” rather than “what can we deliver in the near term.”

The syntax (and some of the semantics) will take an extended subset (I love that phrase) of Java as a starting point, for all the arguments one finds for such an approach in Gabriel’s “Worse is Better” philosophy. I decided to put off, for now, a more complete exploration of the applicative space, until we understand the Von Neumann space better. I know that the applicative / functional approach that Rune and I have been talking about simply makes many of the current DCI problems irrelevant. Nonetheless, they are still real problems in the Von Neumann world and I’m putting my money on that world as being the first place where DCI is likely to be accepted and applied.

The environment will be written entirely (cross fingers) in Java (yes, I’ve really sold my soul…) so we avoid the kinds of problems that I faced with  not being able to bring up Squeak on my machine. Java is the ultimate computer virus: it is ubiquitous. And it’s marginally more portable than C. So I hope that everyone here on the list will eventually be able to bring up the environment on one of their own machines and contribute to the effort.

It’s an understatement to say that this is a large effort and I don’t intend to do it alone. I intend to spend a few months (probably the summer) working on it alone to get it to a point of cogency. At that point I’ll open it up to a small community for review and for one or two rounds of refinement. My long-term goal is to open-source the environment (probably on GitHub), probably six months or so down the road.

I hope that I can build something that is correct by design with an eye on all of the postulates. Of course there will be testing, because details get lost and mistranslated along the stages of development. But I don’t want to depend either on hope or guesswork, because this is where I see most of the cross-language efforts struggling. That is, the run-time should be designed to be memory-safe, with design guarantees against both dangling pointers and unreferenceable zombie objects. It should be designed so an object’s state can’t be modified while any activation record is open on a method of any Role that object is playing, except from within the code of that corresponding Role method. OOPSLA never admitted any garbage collection paper without an accompanying formal proof, and we should hold ourselves up to no lower standard. That’s why I’m taking ownership of both the language and of the virtual machine.

For example, I want to be able to reason about the Context stack not from the point of how I’m limited or enabled by the underlying technology, but in terms of how live people think about what’s going on in the program. I want Kant to reflect that perspective in its syntax, its underlying semantics, and in how the semantics are implemented,

The front-end will be a full-blown compiler with robust semantic analysis. I have seen source translation pop up many times on this list and I have enough bad experiences in that area to know to avoid it. At best, source translation can insulate the source language from the object code. Thinking more broadly — in terms of an environment rather than just the language — source translation suffers heavily in areas of integrating debuggers, analysers, configuration management, basic memory management algorithms, and the like. In any case I want to be able to do full semantic analysis and to build a robust source-level type system, because I feel that there is much that can be done at compile time to support and guarantee the postulates. That more or less rules out Squeak as a research platform, by the way — it’s just too counter-cultural there. I’ve seen too many source translation effort fall short of being full-gledged compilers, stopping at being some simple Perl script that is minimally invasive into the original source and basically ignores most of the source but just passing it along. This has to be a real compiler.

As aside: Many people confuse “type system” with “strong compile-time type checking” and too many people confuse “strong compile-time type checking” with Pascal. (For example, people don’t understand that Smalltalk has a much stronger type system than C++ — it’s just that it’s operative at run-time instead of compile-time). I hope to take a typing approach much more inspired by the likes of Objective-C than by Pascal or C++. It almost goes without saying that there will be a strong separation between class and type, and that most typing will be duck-typing. Most importantly, there is a whole spectrum of typing approaches to be explored. For example:

  • Should we require the programmer to make the Role / Object interface explicit?
  • Can we use type inference to automatically generate the Role / Object interface?
  • How much of the Role / Object contract checking can be moved from run-time (where everything is possible) to compile-time (which may need help from the programmer)?
  • Can we just use a reference to an Abstract Base Class as a way for the Role to document the expected interface for its objects instead of extending the concept of Role to itself declare this interface?
  • Should Roles and Stage Props be separate linguistic constructs, or should a Stage Prop just be a Role with a suitable notation that modifies the semantics?

That’s why I want an experimental environment, with a real compiler, unconstrained by the type semantics of any host language.

The first code generators are likely to generate threaded code for the virtual object machine, or to just drive an interpreter. If someone wants to explore code generation (especially for the JVM) I’ll encourage such efforts to go forward once the code is open sourced.

How will I know when we are done? That’s the wrong question. I’m taking up this initiative to be able to cleanly, and with integrity and discipline, uncompromisingly explore the hard questions of DCI. I find that I am blocked every time I try to do this in an existing language. It’s a bit scary how little we have explored the detailed semantics (per my most recent postulates). The product is understanding and knowledge. Such outputs might help guide the pidgin efforts, but my fantasy is that they can modulate the future evolution of language in the industry, and maybe contribute to the evolution of existing language platforms.

As for whether this direction causes Trygve and I to diverge, we’ll have to see. I am not too worried for now: As Trygve pointed out, he and I are each bringing our own perspective and focus and each has value in its own right. My own opinion is that the efforts to adapt DCI to languages such as Javascript should take note of what we learn from the Kant research effort, whereas on the other hand the Kant effort has the luxury of being free from the considerations of any given technology or language.

So stay tuned. I hope to be back in a few months.

Matthew Browne

unread,
Jun 24, 2015, 8:18:37 AM6/24/15
to object-co...@googlegroups.com
I started a new thread for this, to help keep things organized:
https://groups.google.com/forum/#!topic/object-composition/mU4RFGM-JO0

Thanks,
Matt

Egon Elbre

unread,
Jun 24, 2015, 8:49:58 AM6/24/15
to object-co...@googlegroups.com

On Wednesday, 24 June 2015 14:42:14 UTC+3, Cope wrote:
This is an update on my planned work to advance DCI.

I have abandoned my Squeak efforts for want of being able to procure a working version for my Mac. And as I looked at my project to convert Objective-C to DCI I found what many of you are finding in your attempts with other languages, and in particular the recent forays with Javascript. It quickly becomes fragile and is susceptible to incorrect implementations (e.g., accidentally re-introducing wrapper semantics). Further it’s difficult to achieve a syntax that is acceptable, let alone worthy of being excited about. (The adding of extra parenthesis is all-too-reminiscent of the gratuitous curly braces one needs to add in Java to create an anonymous subclass to overcome the type erasure bug in the language — https://code.google.com/p/guava-libraries/wiki/ReflectionExplained).

More broadly, almost all of our work has been based on ports to existing languages, with all of their attendant warts and historical baggage. I became concerned that this is crippling our ability to nurture the dialogue on whither DCI and to refine the computational model instead of just working the engineering issues. The engineering exercises try to introduce as much of the DCI computational model as possible into existing infrastructure, but the incompatibilities leave us always coming up short — at least with respect to the postulates I posted here some time ago. What’s scarier is that these environments usually leave us in a position where we can’t even reason about some of the postulates. I am starting to feel as though we’re going around in circles, as the same issues recur.

I propose to start from scratch, and have designed a new language explicitly with DCI in mind. I want to name the language Trygve but won’t do so until I have his permission. In the mean time it’s named Kant. In the spirit of Smalltalk it will be not just a language but an integrated environment. Both the language and the environment will be meagerly featured, more suitable to a research effort than to the production of any code.

The environment will include an “object machine.” In our work thus far, that part of DCI has been supplanted by the limitations of the run-time environments beneath the respective languages we’ve strived to evolve. I want an environment without excuse for compromise. That means we can have discussions about “what is the right thing to do” rather than “what can we deliver in the near term.”

The syntax (and some of the semantics) will take an extended subset (I love that phrase) of Java as a starting point, for all the arguments one finds for such an approach in Gabriel’s “Worse is Better” philosophy.

I dislike Java syntax quite a lot, mainly that the verbosity of the language hides the actual thing being done, but I can understand the reasoning for choosing it.
 
I decided to put off, for now, a more complete exploration of the applicative space, until we understand the Von Neumann space better. I know that the applicative / functional approach that Rune and I have been talking about simply makes many of the current DCI problems irrelevant. Nonetheless, they are still real problems in the Von Neumann world and I’m putting my money on that world as being the first place where DCI is likely to be accepted and applied.

The environment will be written entirely (cross fingers) in Java (yes, I’ve really sold my soul…)

Just a tip - not sure how familiar you are with Java tools - use hot-loading in Java, it can make iterating on code faster. e.g. HotSwap/JRebel
 
so we avoid the kinds of problems that I faced with  not being able to bring up Squeak on my machine. Java is the ultimate computer virus: it is ubiquitous. And it’s marginally more portable than C.

I've had plenty of trouble of bringing up a Java based projects. I can still remember one project requiring me to download ~1.5GB of dependencies, plus needed to make tons of configuration, before I was able to get it running in a broken state. But, this is mainly project layout and dependency problem rather than a language problem.

So I hope that everyone here on the list will eventually be able to bring up the environment on one of their own machines and contribute to the effort.

It’s an understatement to say that this is a large effort and I don’t intend to do it alone. I intend to spend a few months (probably the summer) working on it alone to get it to a point of cogency. At that point I’ll open it up to a small community for review and for one or two rounds of refinement. My long-term goal is to open-source the environment (probably on GitHub), probably six months or so down the road.

... snip ...

So stay tuned. I hope to be back in a few months.

Definitely looking forward to it. :)

+ Egon

James O Coplien

unread,
Jun 24, 2015, 9:09:51 AM6/24/15
to object-co...@googlegroups.com
On 24 Jun 2015, at 14:49, Egon Elbre <egon...@gmail.com> wrote:

I dislike Java syntax quite a lot, mainly that the verbosity of the language hides the actual thing being done, but I can understand the reasoning for choosing it.

I hate Java with a passion. But given the goals, that’s irrelevant.


Just a tip - not sure how familiar you are with Java tools - use hot-loading in Java, it can make iterating on code faster. e.g. HotSwap/JRebel

I can iterate as fast as I need to with Eclipse. I want to keep my tool inventory small; that’s always an impediment to technology transfer.


I've had plenty of trouble of bringing up a Java based projects. I can still remember one project requiring me to download ~1.5GB of dependencies, plus needed to make tons of configuration, before I was able to get it running in a broken state. But, this is mainly project layout and dependency problem rather than a language problem.

Do you have an alternative suggestion?


Greg Young

unread,
Jun 24, 2015, 9:15:24 AM6/24/15
to object-co...@googlegroups.com
As a thought why not try using say beam as the vm? its reasonably
portable and easy to compile to. It also is message centric.
> --
> You received this message because you are subscribed to the Google Groups
> "object-composition" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to object-composit...@googlegroups.com.
> To post to this group, send email to object-co...@googlegroups.com.
> Visit this group at http://groups.google.com/group/object-composition.
> For more options, visit https://groups.google.com/d/optout.



--
Studying for the Turing test

Egon Elbre

unread,
Jun 24, 2015, 10:57:43 AM6/24/15
to object-co...@googlegroups.com
On Wednesday, 24 June 2015 16:09:51 UTC+3, Cope wrote:

On 24 Jun 2015, at 14:49, Egon Elbre <egon...@gmail.com> wrote:

I dislike Java syntax quite a lot, mainly that the verbosity of the language hides the actual thing being done, but I can understand the reasoning for choosing it.

I hate Java with a passion. But given the goals, that’s irrelevant.


Just a tip - not sure how familiar you are with Java tools - use hot-loading in Java, it can make iterating on code faster. e.g. HotSwap/JRebel

I can iterate as fast as I need to with Eclipse. I want to keep my tool inventory small; that’s always an impediment to technology transfer. 

They are optional and don't become a dependency of your projects. They just help to avoid compile+wait. But, I do understand the need to keep things simple.
 

I've had plenty of trouble of bringing up a Java based projects. I can still remember one project requiring me to download ~1.5GB of dependencies, plus needed to make tons of configuration, before I was able to get it running in a broken state. But, this is mainly project layout and dependency problem rather than a language problem.

Do you have an alternative suggestion?

Something that would be significantly better, probably not.

My personal thoughts about languages...

Java/C#, gets the job done, but I feel miserable after writing it :). There's MPS that might help with prototyping https://www.jetbrains.com/mps ... but since it's a research language, MPS might get in the way instead of helping. Examples http://www.codeproject.com/Articles/50377/Create-Your-Own-Programming-Languagehttps://github.com/NewLisper/yin

I would use Go, but that's just a personal preference. It's an easy language and it's hard to write bad code with it. It does not have a lot of surprising behavior - in principle it's cleaned up C with GC. Most projects can be installed with "go install github.com/xxx" + easy to cross-compile to multiple places (including web). After compiling you'll get a statically compiled binary that's easy to distribute. Of course there are downsides - no helpful debugger, and GUI story is not as good as in Java, but bindings to GUI libraries do exist. If you build the GUI inside the environment, then that distinction probably doesn't make a difference. Examples https://github.com/robpike/ivy, https://github.com/ark-lang/ark and more here https://github.com/golang/go/wiki/projects#virtual-machines-and-languages

Using JavaScript would be a possibility. Ubiquitous language of the web, containing plenty of surprises. If you have a browser, you pretty much can run it. Downsides - no static typing built in, no great package management. For research purposes, probably you can get something up and running faster than in other languages - but as time goes on, it becomes unwieldy. Examples http://lisperator.net/pltut/ and http://www2.tcl.tk/20291

From hear-say F# and O'Caml are good language for building up DSL/languages because of pattern matching and other language features; although I don't have any direct experience... It would set the understanding bar of language higher. Of course since most of the time will be spent on the environment rather than the language, I'm not sure whether they help there. Example http://llvm.org/docs/tutorial/OCamlLangImpl1.html

Ruby, Python, Haxe - never managed to build up trust for those languages, so I usually stay away from them. Although implementation story would be probably similar to JS. Rust/D you'll essentially get a better and cleaner C++ to work with. Clojure/Scheme/lisps... I've found the compilation and project management annoying; and for me it's hard to keep the code nice and readable.

Regarding compiling to an existing VM, I would advise against it, at least in the beginning. You'll start having problems with small things that probably are irrelevant to the problem at hand. (Not saying that there won't be problems with implementing your own VM.)

tl;dr; use what you feel comfortable with and the language that gets least on your nerves. Annoyance is a good way to kill interest and drive.

Not sure whether this write-up helps or not. At least you can look at the examples that some languages produce.

+ Egon

James O Coplien

unread,
Jun 24, 2015, 11:02:06 AM6/24/15
to object-co...@googlegroups.com

> On 24 Jun 2015, at 15:15, Greg Young <gregor...@gmail.com> wrote:
>
> As a thought why not try using say beam as the vm? its reasonably
> portable and easy to compile to. It also is message centric.

Because there is nothing message-centric about DCI, nor anything else central to DCI that is more centric to beam than to anything else. And it’s lacking in most of the machine support I’d want for DCI, so I’d have to build a whole virtual machine layer on top of it, anyhow.

I want total control of the machine to start with. I want to borrow some of the signature-checking ideas from the (hardware) of the iAPX 432. I want absolutely no constraints on what I can change, tailor, or throw away for want of starting over.

James O Coplien

unread,
Jun 24, 2015, 11:03:46 AM6/24/15
to object-co...@googlegroups.com
On 24 Jun 2015, at 16:57, Egon Elbre <egon...@gmail.com> wrote:

Regarding compiling to an existing VM, I would advise against it, at least in the beginning.

+1.

tl;dr; use what you feel comfortable with and the language that gets least on your nerves. 

But long-term revenge can also be a tasty motivator.

James O Coplien

unread,
Jun 24, 2015, 11:04:49 AM6/24/15
to object-co...@googlegroups.com
On 24 Jun 2015, at 16:57, Egon Elbre <egon...@gmail.com> wrote:

They just help to avoid compile+wait. 

What kind of environment do you run in? My compile + wait turnaround time has been < 5 seconds — and that’s on an old machine.

Greg Young

unread,
Jun 24, 2015, 11:20:39 AM6/24/15
to object-co...@googlegroups.com
Can you explain a bit more?

"And it’s lacking in most of the machine support I’d want for DCI, so
I’d have to build a whole virtual machine layer on top of it, anyhow"

Which machine support is missing exactly?

Egon Elbre

unread,
Jun 24, 2015, 11:21:43 AM6/24/15
to object-co...@googlegroups.com
Usually, I want seamless sub-second experience, without needing to wait for things. When I make a change in code - I want it to be reflected immediately after I save a file, in the running state of the program. Of course it's not always possible to do a hot-patch to the program, but it works most of the time.


I can live without it, so it's not an essentially feature.

+ Egon

Egon Elbre

unread,
Jun 24, 2015, 11:31:18 AM6/24/15
to object-co...@googlegroups.com


On Wednesday, 24 June 2015 18:04:49 UTC+3, Cope wrote:

On 24 Jun 2015, at 16:57, Egon Elbre <egon...@gmail.com> wrote:

They just help to avoid compile+wait. 

What kind of environment do you run in?

Regarding current environment:

Most of the time I live in SublimeText/some terminal for Go and JavaScript/CSS and have few helper programs that do an automatic recompile/restart for Go server/programs and hot-patch update in JavaScript/CSS.

I don't write Java often, but when I do, I use IntelliJ.

James O Coplien

unread,
Jun 24, 2015, 12:28:27 PM6/24/15
to object-co...@googlegroups.com

> On 24 Jun 2015, at 17:20, Greg Young <gregor...@gmail.com> wrote:
>
> Which machine support is missing exactly?


Does it support capability-based addressing?

Does the hardware have an address chain reachability primitive (given an address range, is there any word in memory that references an object whose references recursively can reach that address range)?

Does the hardware include CAM (content-addressable memory) addressing?

Is the endianness of the machine configurable? How about sign extensibility of abelian primitives?

Does the native hardware support UNICODE characters and UNICODE-based addressing?

Is garbage collection reconfigurable between reference counting (with a local per-activation-record memory pool, as in Objective-C), mark-sweep, and generation scavenging?

Is disk addressing a logical extension of main memory addressing (as in Apollo DOMAIN), or can it be configured as such?

Does the architecture support memory-mapped graphical I/O?

Does the architecture support an arbitrarily large number of change traps so that I can set a monitor on a given object, and the environment will create a trap or activate a callback whenever a given memory range is read? written? either?

You get the idea.


James O Coplien

unread,
Jun 24, 2015, 12:29:06 PM6/24/15
to object-co...@googlegroups.com

On 24 Jun 2015, at 17:31, Egon Elbre <egon...@gmail.com> wrote:

I don't write Java often, but when I do, I use IntelliJ.


Should I consider using it instead of Eclipse?

Egon Elbre

unread,
Jun 24, 2015, 12:57:25 PM6/24/15
to object-co...@googlegroups.com
Friends who work mainly with Java recommend it over Eclipse. To me IntelliJ feels faster, smarter, more usable and more responsive. I'm using IntelliJ Community Edition (free), which has all the necessary things for me. So, I like it more than Eclipse and would recommend it over Eclipse.

If interested you can read more here, from people who actually develop Java every day:

+ Egon

Benjamin Scherrey

unread,
Jun 25, 2015, 11:58:59 AM6/25/15
to object-composition
On Wed, Jun 24, 2015 at 8:09 PM, James O Coplien <jcop...@gmail.com> wrote:

On 24 Jun 2015, at 14:49, Egon Elbre <egon...@gmail.com> wrote:

I dislike Java syntax quite a lot, mainly that the verbosity of the language hides the actual thing being done, but I can understand the reasoning for choosing it.

I hate Java with a passion. But given the goals, that’s irrelevant.

Enjoying a programming language's semantics and architectural drivers is what causes me to want to code in that language. As painful as Stroustrup's adoption of C as the basis of C++ was, he pretty much nailed the balance and tradeoffs and finally the latest C++ standards are leaving some of those problems behind. Honestly outside of that I've never seen it successfully done otherwise (and you know how long it took even then) and I certainly wouldn't be one to try to build something innovative on top of Java which never was designed with such clean drivers (as K&R did) and had the unfortunate habit of standardizing things way too prematurely. So I feel this is entirely relevant. The world does not need another C-like syntax imperative/object-like language of any sort. C#, go-lang, etc included. It's really not hard to do better.
 
Just a tip - not sure how familiar you are with Java tools - use hot-loading in Java, it can make iterating on code faster. e.g. HotSwap/JRebel

I can iterate as fast as I need to with Eclipse. I want to keep my tool inventory small; that’s always an impediment to technology transfer.


Eclipse is another huge abomination. I honestly don't see how people get productive in it. Of course starting off with java is like breaking your arm then using Eclipse/ant is like putting on a cast and saying, "Now, isn't that better?" :-) [ok I admit I'm ranting here but this is my personal opinion/experience]

I've had plenty of trouble of bringing up a Java based projects. I can still remember one project requiring me to download ~1.5GB of dependencies, plus needed to make tons of configuration, before I was able to get it running in a broken state. But, this is mainly project layout and dependency problem rather than a language problem.

Do you have an alternative suggestion?

Several. As it turns out I've been thinking along very similar lines although I have some different goals like ultimately realizing the primitives of my language as the instruction set of a hardware cpu via fpga and ultimately asic so you will see a bias towards smallness and stack orientation.

One thing I do require is an interactive system where the programmer/user has an active conversation with the computer and the objects within it in terms of definition, implementation, testing, operation. I should be able to conduct the full life cycle of development/deployment/usage via a terminal and have it persist.

First off - the best language in the world to implement new languages is forth. When I say forth I mean all threaded interpreted stack-based languages and definitely not ANS FORTH. The syntax of "standard" forth is highly optimized for it's implementation/environment but that isn't necessary at all and building entire languages and working systems on top of these primitives is something that can be done in a few weeks from scratch. Basically everything people love about lisp but actually practical and extendable based on concatenative programming styles. Building in contexts and roles is really fairly straightforward - in fact too straightforward as there are a dozen or so obvious ways to do it. Downside here is you're really building everything yourself from scratch including any GUI tools.

Going a bit more "mainstream" with more popular support I would suggest targeting the python VM machine which is also stack based. There are now excellent tools that can optimize any AST and generate highly optimized runtimes based on this target - even if you never actually run on a python VM. It also runs absolutely everywhere and would be easy to integrate with C/python apps/tools that exist today. I happen to do most of my development these days with python even though C++ is probably my strongest language. 

Another odd option is a rather new language which is a complete program/os system called Red http://www.red-lang.org/p/about.html which is an open source decendent of Rebol. It's quite small, self contained, and focuses on the idea of tools helping the programmer. I haven't dug into the details of it's implementation yet but it seems reasonable that it could be forked and turned into something that supports DCI natively without incredible effort. 

My ideas so far have been firmly in the forth-ish model but honestly I've never little time to flesh anything out. My language would look unlike any forth ever implemented (albeit I might keep the postfix style) but behind the scenes there is little doubt to it's foundations. If my primary focus was to experiment with language architecture (meaning lots of iterations and attempts at implementations via trial & error), I don't think there's any more productive option for such experiments than a threaded interpreted concatenative stack based language.

If I were more focused on winning public adoption of the language as Stroustrup was with C++, then I might lean more towards the python/VM model as there is a lot of room to play and still make your code very understandable and even convertible into running python ala the old cfront (pyfront anyone?). You can already see this happening with tools such as cython which let you inject some minor static typing and otherwise your 99.99% python code is running 100x faster as compiled C. The python vm, language structure, and all it's built-in reflection capabilities really lend itself towards what you're trying to do more than the JVM.

I'd probably get my language working via the forth model first (via several iterations) then port it to a higher level system like the python/vm (or even JVM at that point if it makes sense). 

Thems my 2 cents. But I'm excited that you're going this way however you do it as I think DCI needs to be designed into a language for it to be properly realized. And that's my intent.

  -- Ben

 


--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.



--
Chief Systems Architect Proteus Technologies
Personal blog where I am not your demographic.

This email intended solely for those who have received it. If you have received this email by accident - well lucky you!!

Egon Elbre

unread,
Jun 25, 2015, 2:00:59 PM6/25/15
to object-co...@googlegroups.com


On Thursday, 25 June 2015 18:58:59 UTC+3, Ben Scherrey wrote:


On Wed, Jun 24, 2015 at 8:09 PM, James O Coplien <jcop...@gmail.com> wrote:

On 24 Jun 2015, at 14:49, Egon Elbre <egon...@gmail.com> wrote:

I dislike Java syntax quite a lot, mainly that the verbosity of the language hides the actual thing being done, but I can understand the reasoning for choosing it.

I hate Java with a passion. But given the goals, that’s irrelevant.

Enjoying a programming language's semantics and architectural drivers is what causes me to want to code in that language. As painful as Stroustrup's adoption of C as the basis of C++ was, he pretty much nailed the balance and tradeoffs and finally the latest C++ standards are leaving some of those problems behind. Honestly outside of that I've never seen it successfully done otherwise (and you know how long it took even then) and I certainly wouldn't be one to try to build something innovative on top of Java which never was designed with such clean drivers (as K&R did) and had the unfortunate habit of standardizing things way too prematurely. So I feel this is entirely relevant. The world does not need another C-like syntax imperative/object-like language of any sort. C#, go-lang, etc included. It's really not hard to do better.
 
 
Just a tip - not sure how familiar you are with Java tools - use hot-loading in Java, it can make iterating on code faster. e.g. HotSwap/JRebel

I can iterate as fast as I need to with Eclipse. I want to keep my tool inventory small; that’s always an impediment to technology transfer.


Eclipse is another huge abomination. I honestly don't see how people get productive in it. Of course starting off with java is like breaking your arm then using Eclipse/ant is like putting on a cast and saying, "Now, isn't that better?" :-) [ok I admit I'm ranting here but this is my personal opinion/experience]

I've had plenty of trouble of bringing up a Java based projects. I can still remember one project requiring me to download ~1.5GB of dependencies, plus needed to make tons of configuration, before I was able to get it running in a broken state. But, this is mainly project layout and dependency problem rather than a language problem.

Do you have an alternative suggestion?

Several. As it turns out I've been thinking along very similar lines although I have some different goals like ultimately realizing the primitives of my language as the instruction set of a hardware cpu via fpga and ultimately asic so you will see a bias towards smallness and stack orientation.

One thing I do require is an interactive system where the programmer/user has an active conversation with the computer and the objects within it in terms of definition, implementation, testing, operation. I should be able to conduct the full life cycle of development/deployment/usage via a terminal and have it persist.

First off - the best language in the world to implement new languages is forth. When I say forth I mean all threaded interpreted stack-based languages and definitely not ANS FORTH. The syntax of "standard" forth is highly optimized for it's implementation/environment but that isn't necessary at all and building entire languages and working systems on top of these primitives is something that can be done in a few weeks from scratch.

Any particular implementation that you would suggest?  Also do you know any good examples of languages implemented in it? I haven't looked at Forth for a while and I probably should revisit it.

+ Egon

James O Coplien

unread,
Jun 25, 2015, 2:20:27 PM6/25/15
to object-co...@googlegroups.com

On 25 Jun 2015, at 17:58, Benjamin Scherrey <prote...@gmail.com> wrote:

Enjoying a programming language's semantics and architectural drivers is what causes me to want to code in that language. As painful as Stroustrup's adoption of C as the basis of C++ was, he pretty much nailed the balance and tradeoffs and finally the latest C++ standards are leaving some of those problems behind. Honestly outside of that I've never seen it successfully done otherwise (and you know how long it took even then) and I certainly wouldn't be one to try to build something innovative on top of Java which never was designed with such clean drivers (as K&R did) and had the unfortunate habit of standardizing things way too prematurely. So I feel this is entirely relevant. The world does not need another C-like syntax imperative/object-like language of any sort. C#, go-lang, etc included. It's really not hard to do better.

Well… no. The purpose is not to explore the design of a language. The purpose is to explore a computational model. The language is just a necessary evil — a scaffolding — necessary to exercise the virtual machine. Trust me: if it gets in the way, I’ll change it.

One has to start somewhere. One doesn’t start with either truth or beauty, but with the success of the vulgar and the vernacular. Smalltalk might be the most beautiful syntax (I doubt it) but even if it were, no one will line up for it. We’ve already seen that. If it has a Java sheen I’ll get engagement. And I’ve always been after engagement and community.

Again: I’m not after adoption, but research engagement. If I were after adoption then I’d find your comments more valuable. And if I followed any guide that led me towards a perfect syntax, it will likely subsconsciously keep me from changing the language, out of fear of making it ugly. As you point out, designing a good language is hard. I was the first user of C++ outside of Bell Labs research and I gave up watching it evolve about ten years ago — the latest adaptations are irrelevant. They are never going to go down in history as having contributed to the greatness of any piece of software.

And that is exactly the mission here. I don’t have 30 years to wait for language syntax to converge. The language may be a little clunky. I’ve been around long enough to know that it’s better to start with something than to shoot from the hip and, as I said, I chose my starting point wisely, based on popularity. Vulgar, I know. Yet I have never — never — seen a single research paper that was properly based in a good research methodology that ever showed any benefit due to language.

Let’s not sweat the small stuff. I don’t care what the world needs and doesn’t need in terms of syntax. I’m setting my sites much higher.  Í aspire to a great computational model which will itself lend itself well to human sensibilities, and a syntax that follows vox populi.

James O Coplien

unread,
Jun 25, 2015, 2:26:33 PM6/25/15
to object-co...@googlegroups.com
Benjamin,

Most of your suggested languages (Forth, python) are a pain to integrate with a good parser generator, and lack the kind of things that I find support me in this style of programming, like good type checking. That was the first thing that Stroustrup went after in his bootstrapping effort. But he was smart enough to choose something that would integrate with yacc. If I’m evolving a language, I want the code to articulate the stuff I’m working with and evolving. That means a good articulation of the grammar. Doing a parser manually is not to my taste.

Further, they don’t have large developer communities out there — relative to Java. Certainly not Red. I’ve said that three times now. Y’all hear me?

Benjamin Scherrey

unread,
Jun 25, 2015, 3:05:32 PM6/25/15
to object-composition
Cope,

   Understand your concerns. Perhaps I misunderstood you but I thought you were trying to build a language around DCI and not bolt DCI onto a language. Maybe you've thought it further than I have but I just don't see Java syntax mapping so well although I can see how targeting the JVM is an interesting option. Again I didn't suggest you use python as the language, I suggested you (eventually - not at first) target the python VM as an alternative to the java VM. But if the VM isn't your interest then it's not relevant. 

   Regarding integration with a parser/generator - agree regarding python. But forth, well it's got every language spanked when your interest is designing a language/computing engine quickly and iterating over key architectural options. See http://www.bradrodriguez.com/papers/bnfparse.htm for a full bnf implementation in under 40 lines of code. You can build your syntax to look just like java and generate jvm bytecode to boot if it makes you feel better. I just think building this computing engine in java is going to be a rather painful experience.

    Anyway - I think you've already set your mind on your implementation foundations. I'm curious what your thoughts are regarding the priority/desirability for an interactive programming environment.

    Best of luck!

  -- Ben

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

Greg Young

unread,
Jun 25, 2015, 3:13:15 PM6/25/15
to object-co...@googlegroups.com
" Understand your concerns. Perhaps I misunderstood you but I thought
you were trying to build a language around DCI and not bolt DCI onto a
language. Maybe you've thought it further than I have but I just don't
see Java syntax mapping so well although I can see how targeting the
JVM is an interesting option."

My understanding is that the environment would be jvm based but the
runtime would be a new runtime although I have to admit this thread
has seemed to jump between ideas and understandings @james is this the
case?

Benjamin Scherrey

unread,
Jun 25, 2015, 3:19:05 PM6/25/15
to object-composition
Egon,

    Most serious forth-ers implement their own (it's just that easy to do). But there are solid implementations for just about any target you want. Regarding languages implemented with it - most forth apps are DSLs, frankly. Forth-ers are a seriously minimalistic lot and tend to build specialized systems rather than general ones. You'll also rarely see it outside of resource limited environments like embedded systems. However there's absolutely nothing that makes it inappropriate or difficult to scale up except the near asm-like primitives. That's why my suggestion is to build a threaded interpreted stack-based language that is higher level which can be done either on a standard forth or strictly on top of your own custom engine (my personal direction). My focus has always been on "forth-like" languages rather than forth itself. Actually a language called Factor ( https://en.wikipedia.org/wiki/Factor_(programming_language) ) was inspired by forth and originally implemented on the JVM so you can see how this architectural style can be implemented at a lot of different levels. 

  -- Ben

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

Egon Elbre

unread,
Jun 25, 2015, 4:27:35 PM6/25/15
to object-co...@googlegroups.com


On Thursday, June 25, 2015, Benjamin Scherrey <prote...@gmail.com> wrote:
Egon,

    Most serious forth-ers implement their own (it's just that easy to do).

I know the effort for Forth core, implemented one a while ago. I just thought you had something particular in mind.
 
You received this message because you are subscribed to a topic in the Google Groups "object-composition" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/object-composition/nnxDYYMC5qc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

James O Coplien

unread,
Jun 26, 2015, 4:59:31 AM6/26/15
to object-co...@googlegroups.com

> On 25 Jun 2015, at 21:13, Greg Young <gregor...@gmail.com> wrote:
>
> My understanding is that the environment would be jvm based but the
> runtime would be a new runtime although I have to admit this thread
> has seemed to jump between ideas and understandings @james is this the
> case?

Yes, think Benjamin was confusing two things.

Trygve Reenskaug

unread,
Jun 26, 2015, 11:36:02 AM6/26/15
to object-co...@googlegroups.com
On 24.06.2015 13:42, James O Coplien wrote:
I propose to start from scratch, and have designed a new language explicitly with DCI in mind. I want to name the language Trygve but won’t do so until I have his permission. In the mean time it’s named Kant. In the spirit of Smalltalk it will be not just a language but an integrated environment. Both the language and the environment will be meagerly featured, more suitable to a research effort than to the production of any code.
I'll be honored if you choose to name your new language after me. You and I have over the years evolved the same vision about what DCI is all about. There has been disagreement about implementation: Adapt a mainstream language or build the DCI semantics on the changing Smalltalk. Your new language will bring this discussion to a conclusion: Reject all of them. I look forward to continue our productive discussions.

Your new language is designed for DCI so I presume its target audience is end users and other nonprofessional programmers. The ARTICLE still awaits its killer example, your new language will be ideal for this and I hope it will help us find a suitable use case.

I have, of course, many concerns, ideas, and suggestions. They are probably not welcome at this stage of your work and I have 99 unread DCI messages in my inbox. So I leave you to it and wish you the best fortunes for your groundbreaking work.

--Trygve

James O Coplien

unread,
Jun 26, 2015, 11:49:26 AM6/26/15
to object-co...@googlegroups.com

On 26 Jun 2015, at 17:35, Trygve Reenskaug <try...@ifi.uio.no> wrote:

Your new language is designed for DCI so I presume its target audience is end users and other nonprofessional programmers. 

The first implementation will look much like Java, much because we need the feedback of professional programmers at this time. There are a lot of technical issues to iron out and we need technical people to look at them. Making a Java look-alike will draw them in.

The feedback we’d get from non-programmers is likely to be orthogonal to what I want from the project.

Also, I’m a big fan of domain-specific languages. To build a general-purpose programming language for non-programmers is oxymoronic. At this time I think that refining our computational model ideas would be difficult if we restricted ourselves to a given discipline or domain. That will come as a raft of later refinements years down the road. And it will be a lot of work — we’d need to engage a community of domain experts in some domain to make such a project viable.

The project is much less about the language than the computational model.

I have thought about about a higher-level front end, based on Rebecca’s table-style use cases. I have a model in mind that would allow the programmer to elaborate Actors into what we know as Roles. Each screen would be a use case — a Context. The columns would be written in very highly structured natural language. But I think that leg of the project is more than a year away. (And I’d like to get Rebecca involved. I don’t doubt that maybe someone has tried something similar before, and I want to tap whatever insight she has into such work.)

Rune Funch Søltoft

unread,
Jun 26, 2015, 3:21:25 PM6/26/15
to object-co...@googlegroups.com
To me a very interesting part is the VM and the execution model. An execution environment that supports DCI semantics (what they will turn out to be) will make the discussion of original syntax somewhat irrelevant. Since creating a new language that uses the same back would be a comparatively small effort

Mvh
Rune
--

James O Coplien

unread,
Jun 26, 2015, 4:46:53 PM6/26/15
to object-co...@googlegroups.com
+1.

Benjamin Scherrey

unread,
Jun 28, 2015, 11:42:46 AM6/28/15
to object-composition
Actually I don't believe I was confusing the two things as I made the distinction pretty clear. My questions/observations were an attempt to try to understand your motivations and boundaries for the distinction. 

The main question that immediately came to mind is "Why java?"

The reasons that come to mind and questions that they lend are:

 Is it for a) the ubiquitous JVM target, 

                 Which makes sense to me but has very little to do with Java as a language or computing model because it's simply an object-like stack machine which actually has some pretty annoying limitations not shared with other ubiquitous VMs such as the python or CLR ones which both share the positive attributes you assign to the JVM. But if this is the primary reason then you're likely to be designing a new language from scratch because...

             b) to be able to re-use and easily integrate with tons of existing code bases (ala C->C++), 

                 Which, if possible, is probably the most compelling reason to go for it but I also believe this is the most difficult hurdle to overcome. Can you build a language runtime that fully supports and depends on DCI concepts where otherwise normal Java code would still be legal "Trygve" code and could co-exist side by side. Without this seemingly high value result it's difficult to justify the otherwise enourmous difficulties in building such a computing model/language in a language clearly so unsuited for it, IMHO. But my reading from your announcement is that this seems not to be a goal at all but java will simply be the implementation language and the resulting language will likely resemble java superficially once it's usable.

         or c) .... well I had a C when I started writing this but I lost it... :-) something along the lines of it sounds like you just think adoption of the syntactical style will make it easier for people to adopt.

But your emails seem to completely outright deny "a" (as you want your own vm that supports your architectural drivers - here could be my misunderstanding if it's your opinion that the jvm actually does what you want as a target vm), discount "b" (as you don't care about adoption) while implying that you're going code it in java which looks like "c" but your denial of "b" would also eliminate this reason. 

So there is my confusion laid out. 

   -- Ben

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

Matthew Browne

unread,
Jun 28, 2015, 12:15:46 PM6/28/15
to object-co...@googlegroups.com
I was concerned about the choice of Java too, but that's when I thought this was about creating a language for real-world use...My reading of Cope's most recent posts is that Java will generate the most research interest among professional programmers - and maybe computer scientists too (not sure if that was implied?) - due to its sheer popularity and number of people familiar with its syntax. So it's not about creating a language that will actually be used for real programming, just an initial step to get feedback and refine DCI semantics. After better codifying DCI, then the same VM could potentially be used to develop a new DCI language, possibly with syntax quite different from Java. Cope's logic makes sense to me; while I think another language could work too, Java is fine; this is mainly a research project where the initial syntax isn't even a big factor, as long as everyone can basically read it and understand it.
You received this message because you are subscribed to a topic in the Google Groups "object-composition" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/object-composition/nnxDYYMC5qc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

James O Coplien

unread,
Jun 28, 2015, 1:05:58 PM6/28/15
to object-co...@googlegroups.com

On 28 Jun 2015, at 17:42, Benjamin Scherrey <prote...@gmail.com> wrote:

Actually I don't believe I was confusing the two things as I made the distinction pretty clear.

Hmmm. Well, the arguments you make are much different than those behind my motivations.

First, my choice of Java as the language in which the platform will be developed has little (directly) to do with the JVM. It has more to do with the ubiquity of Java development environments. That there is a JVM beneath them is irrelevant to me (though it of course serves them in their own ability to be ubiquitous).

I want people to be able not only to bring up the environment on their machines but to be able to play with it. That means going with a commodity platform. Java is it.

Secondly, regarding the choice of Java syntax as a starting point for the Trygve language: This is just simple “worse is better.”  You can seek finessed reasons for C++ being so well-balanced but the vulgar truth is that people used it because it was “a better C.” Those are Stroustrup’s own words, and it’s what propelled most C++ use in the foundational mid- to late-1980s. Think of Trygve as a “better Java.”

I have no desire to be compatible with any legacy code out there. To have that as a goal would limit my ability to evolve. That was C++’s fate: there were many engineering decisions made out of consideration to backwards compatibility with C. They set early expectations that it would remain compatible, and then when they found that they had to break ranks, it confused the hell out of everyone.

So I’m setting no expectation for compatibility with Java libraries, with the possible exception of really basic stuff like Stack and List and String (which I guess isn’t even a library). I may retrofit other libraries on a custom basis to support oooh-aaah demos (like maybe some of the basic graphics stuff.) But I will not be held hostage to the legacy of engineering decisions Java has left in its wake. Even if they were all good decisions, I am exercising the freedom to move into a different world.

But your emails seem to completely outright deny "a" (as you want your own vm that supports your architectural drivers - here could be my misunderstanding if it's your opinion that the jvm actually does what you want as a target vm),

Right. But that has nothing really to do with the selection of the JVM.


discount "b" (as you don't care about adoption)

That’s correct.

while implying that you're going code it in java which looks like "c" but your denial of "b" would also eliminate this reason. 

And this is why I said you were confusing two things: the ability to re-use and integrate *the environment* with tons of code out there (e.g., to be able to bring it up and evolve it in IntelliJ) without regard to the *Trygve programs* working and playing together with any legacy code in Java (or any other language, for that matter). I think that Greg and I both read your confusion the same way.

So there is my confusion laid out. 

I hope this explanation helps.

But it’s kind of a tempest in a teapot.

James O Coplien

unread,
Jun 28, 2015, 1:06:46 PM6/28/15
to object-co...@googlegroups.com
Matthew,

You’ve summarised it well.

Matthew Browne

unread,
Jun 30, 2015, 10:57:16 PM6/30/15
to object-co...@googlegroups.com
Although Cope is inclined toward Java, maybe after there's a working
prototype, there could be an effort to port it to the Python VM for the
implementation of a language intended for real-world use. Ben, from your
description it sounds promising.

And a fork of Python could of course be one of the languages to get full
DCI support...I think we need a better Python implementation anyhow. The
only one I found to post on the wiki so far was this one:
https://pypi.python.org/pypi/roles

Benjamin Scherrey

unread,
Jul 1, 2015, 1:54:58 AM7/1/15
to object-composition
Matthew,

    Yes the present one requires role injection and it seems that injectionless is the favored mechanism right now. It's not bad considering when it was implemented. Lots more has been learned since then. Certainly python exposes everything required to do this in an officially supported manner so that's a bonus. Cope's concern about manual parser implementations does apply if you're actually trying to build a version that supports/extends the current python language. It may be that we just need to target the python vm and abandon most of python in order to be able to iterate quickly on language changes with the more formal parser definition that I anticipate Cope will understandably want to drive with. Once we see the direction of Cope's model then it will be interesting to see what would be required to implement it in other environments. I'm extremely curious as I'm sure you'd expect. 

  -- Ben

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

James O Coplien

unread,
Jul 1, 2015, 6:07:04 AM7/1/15
to object-co...@googlegroups.com

On 01 Jul 2015, at 07:54, Benjamin Scherrey <prote...@gmail.com> wrote:

Once we see the direction of Cope's model then it will be interesting to see what would be required to implement it in other environments. I'm extremely curious as I'm sure you'd expect. 

I’m more of the opinion that we can learn from this model and create entirely new ones for other technology bindings, based on what we learn from this one. This is, by definition, a prototype. Great design communities throw prototypes away. You can put together a good research prototype in about six months; building what we learn, and starting with an out-of-the-box language grammar, I suspect one could have something up and running in one month. In the larger scheme of things, and with a research view rather than a deployment view, six months is a short amount of time.

"Build one to throw away.” — Fred Brooks

James O Coplien

unread,
Jul 1, 2015, 7:05:12 AM7/1/15
to object-co...@googlegroups.com

> On 01 Jul 2015, at 04:57, Matthew Browne <mbro...@gmail.com> wrote:
>
> Although Cope is inclined toward Java, maybe after there's a working prototype, there could be an effort to port it to the Python VM for the implementation of a language intended for real-world use.

I’m curious — why the Python VM and not that of another language?

The Python VM probably doesn’t support DCI ideas any more than the CLR or the JVM do, so I don’t see an advantage there.

In terms of commercialisation, the latter two have much bigger leverage. I would be thrilled if we set our sites on those.
Reply all
Reply to author
Forward
0 new messages